📡 API REST PÚBLICA · DuckDB · 32M filas
API REST sobre el
presupuesto del Perú.
Un endpoint HTTP que acepta SQL DuckDB y devuelve JSON. Acceso libre a la tabla
mef_historico con
137 columnas y 32M de filas (años 2013-2026). Sin auth, sin API keys, sin SDKs:
cualquier herramienta que hable HTTP puede consumirla.
https://app.gestionpublicaperu.com.pe/api/insights/query Endpoints disponibles
Cuatro rutas, todas bajo https://app.gestionpublicaperu.com.pe.
Sin headers especiales — solo Content-Type: application/json para los POST.
/api/insights/schema Metadata: 137 columnas + tipos, año min/max, total de filas y una query de ejemplo.
— /api/insights/query Ejecuta una query DuckDB sobre mef_historico. Solo SELECT/WITH. Cap 10k filas, timeout 30s.
{ "sql": "SELECT ...", "limit": 1000 } /api/insights/slices/ Lista los JSON precomputados (kpis, evolucion, sectores, categoria, departamentos, pliegos, meta).
— /api/insights/slices/{nombre}.json Sirve un slice JSON específico. Mismo dato que sirve el CDN público, útil para clientes que ya hablan con este origin.
— /api/insights/dimensions Valores distintos de niveles, fuentes, funciones, departamentos, sectores y categorías de gasto. Ideal para poblar dropdowns. Cacheado 5 min.
— /api/insights/serie?sector=11 Serie anual PIM/Devengado/Avance% con filtros simples (sector, pliego, departamento, nivel, fuente, funcion). Sin SQL — solo query params.
— /api/insights/top-sectores?anio=2025 Top sectores por PIM en un año dado. Default = último año cerrado. Devuelve hasta 33 filas con código, nombre, PIM, devengado y avance %.
— Cómo usarla
Cuatro variantes para 4 audiencias. Elegí la que te sirva.
🐚 curl (bash · terminal)
curl -X POST https://app.gestionpublicaperu.com.pe/api/insights/query \
-H "Content-Type: application/json" \
-d '{
"sql": "SELECT anio, ROUND(SUM(MTO_PIM)/1e9, 1) AS pim_mil_M FROM mef_historico WHERE SECTOR LIKE \"11%\" GROUP BY anio ORDER BY anio"
}' 🐍 Python (httpx · ideal para notebooks y scripts)
import httpx
r = httpx.post(
"https://app.gestionpublicaperu.com.pe/api/insights/query",
json={
"sql": """
SELECT anio,
ROUND(SUM(MTO_PIM)/1e9, 1) AS pim_mil_M,
ROUND(SUM(DEVENGADO_)*100
/ NULLIF(SUM(MTO_PIM),0), 1) AS avance_pct
FROM mef_historico
WHERE PLIEGO LIKE '036%' -- MTC
GROUP BY anio
ORDER BY anio
""",
},
timeout=60,
)
data = r.json()
print(data["columnas"]) # ['anio', 'pim_mil_M', 'avance_pct']
print(data["filas"]) # [[2013, 4.2, 87.5], [2014, 5.1, 89.1], ...] 🌐 JavaScript (fetch · browser o Node)
const r = await fetch("https://app.gestionpublicaperu.com.pe/api/insights/query", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
sql: `
SELECT DEPARTAMENTO_META,
ROUND(SUM(MTO_PIM)/1e6, 1) AS pim_M
FROM mef_historico
WHERE anio = 2025 AND DEPARTAMENTO_META != '00 '
GROUP BY DEPARTAMENTO_META
ORDER BY pim_M DESC
LIMIT 5
`,
}),
});
const { columnas, filas, n_filas } = await r.json();
console.table(filas); 📊 Excel · Power Query M
// Excel → Datos → Obtener datos → De otras fuentes → Consulta vacía → Editor avanzado
let
url = "https://app.gestionpublicaperu.com.pe/api/insights/query",
sql = "SELECT anio, ROUND(SUM(MTO_PIM)/1e9, 1) AS pim FROM mef_historico GROUP BY anio ORDER BY anio",
body = Json.FromValue([sql = sql]),
resp = Web.Contents(url, [
Content = body,
Headers = [#"Content-Type" = "application/json"]
]),
json = Json.Document(resp),
tabla = Table.FromRows(json[filas], json[columnas])
in
tabla En Excel: Datos → Obtener datos → De otras fuentes → Consulta vacía → Editor avanzado. Pegá el bloque y refrescá cuando quieras datos nuevos.
Casos de uso reales
Cuatro preguntas frecuentes, con la SQL que las contesta y un preview de la respuesta.
¿Cuánto creció el sector Educación entre 2013 y 2025?
#1SQL:
SELECT anio,
ROUND(SUM(MTO_PIM)/1e9, 1) AS pim_mil_M,
ROUND(SUM(DEVENGADO_)/1e9, 1) AS dev_mil_M
FROM mef_historico
WHERE SECTOR LIKE '10%' -- 10: EDUCACION
GROUP BY anio
ORDER BY anio Output:
anio pim_mil_M dev_mil_M
2013 18.8 17.4
2025 41.1 36.8
→ +118% en 12 años Top 10 pliegos por PIM en 2025
#2SQL:
SELECT PLIEGO,
ROUND(SUM(MTO_PIM)/1e9, 2) AS pim_mil_M
FROM mef_historico
WHERE anio = 2025
GROUP BY PLIEGO
ORDER BY pim_mil_M DESC
LIMIT 10 Output:
PLIEGO pim_mil_M
006. INSTITUTO PERUANO DE SEGURIDAD ... 14.92
036. M. DE TRANSPORTES Y COMUNICACIO... 12.40
010. M. DE EDUCACION 9.87
011. M. DE SALUD 8.54
... Avance de ejecución por nivel de gobierno (2025)
#3SQL:
SELECT NIVEL_GOBIERNO,
ROUND(SUM(MTO_PIM)/1e9, 1) AS pim_mil_M,
ROUND(SUM(DEVENGADO_)*100
/ NULLIF(SUM(MTO_PIM),0), 1) AS avance_pct
FROM mef_historico
WHERE anio = 2025
GROUP BY NIVEL_GOBIERNO
ORDER BY pim_mil_M DESC Output:
NIVEL_GOBIERNO pim_mil_M avance_pct
E. GOBIERNO NACIONAL 180.4 78.3
R. GOBIERNOS REGION... 52.1 82.5
M. GOBIERNOS LOCALES 40.0 71.2 Sin SQL: serie anual de Salud con un GET
#4SQL:
curl "https://app.gestionpublicaperu.com.pe/api/insights/serie?sector=11"
# o también:
# /api/insights/serie?pliego=036 (MTC)
# /api/insights/serie?departamento=15 (Lima)
# /api/insights/serie?funcion=20.%20SALUD
# /api/insights/serie?nivel=R.%20GOBIERNOS%20REGIONALES Output:
{
"filtros": { "sector": "11", ... },
"serie": [
{"anio": 2013, "pim_mil_M": 8.04, "dev_mil_M": 7.31, "avance_pct": 90.9, ...},
{"anio": 2025, "pim_mil_M": 14.52, "dev_mil_M": 14.15, "avance_pct": 97.4, ...}
]
}
→ Ideal cuando no querés escribir SQL. Devengado mensual de Salud en Lima (2025)
#5SQL:
SELECT MTO_DEVENGA_01 AS ene, MTO_DEVENGA_02 AS feb,
MTO_DEVENGA_03 AS mar, MTO_DEVENGA_04 AS abr
FROM mef_historico
WHERE anio = 2025
AND SECTOR LIKE '11%' -- Salud
AND DEPARTAMENTO_META LIKE '15.%' -- Lima Output:
Cada fila es una partida; ideal para
GROUP BY + SUM si querés el agregado.
Devuelve hasta 10.000 filas, agregá
WHERE más fino si tu universo es grande. Límites y reglas
Pensado para análisis ad-hoc, no para producción de aplicaciones críticas. Por ahora sin auth ni rate limit, pero con caps de seguridad razonables.
🛡️
Solo SELECT / WITH
Cualquier intento de INSERT, UPDATE, DELETE, DROP, CREATE, ALTER, COPY, PRAGMA, ATTACH y compañía devuelve HTTP 400. La base es de solo lectura.
📦
Cap 10.000 filas
El backend wrappea tu query con LIMIT 10000.
Si necesitás más, agregá un GROUP BY o
paginá con WHERE anio = ....
⏱️
Timeout 30 segundos
Si la query tarda más, devuelve HTTP 504. La mayoría de queries con
GROUP BY tardan menos de 1s, así que esto
solo aparece con full-scans sin filtros.
🔓
Sin auth, sin keys
Endpoint público. No hay rate limit visible. Si abusás y tirás el server, avísanos primero — sería triste tener que poner barreras.
Schema rápido
Las 15 columnas más usadas. Para la lista completa de 137 columnas y sus tipos, consultá /api/insights/schema .
| Columna | Tipo | Descripción |
|---|---|---|
anio | INT | Año fiscal (2013-2026). Para el año en curso ver es_parcial. |
es_parcial | BOOL | true si es snapshot del año en curso (datos vivos). false si es año cerrado. |
SECTOR | VARCHAR | Formato "NN: NOMBRE" con dos puntos. Filtrá con LIKE 'NN%', nunca con =. |
PLIEGO | VARCHAR | Formato "NNN. NOMBRE" (con punto). Ej "036. M. DE TRANSPORTES...". |
SEC_EJEC | VARCHAR | Código Unidad Ejecutora — sin ceros a la izquierda (ej "154", no "000154"). |
NIVEL_GOBIERNO | VARCHAR | E. GOBIERNO NACIONAL · R. GOBIERNOS REGIONALES · M. GOBIERNOS LOCALES. |
DEPARTAMENTO_META | VARCHAR | Formato "NN. NOMBRE" (con punto). Ej "15. LIMA". Filtrá "00 " (vacío) si querés solo geo válida. |
FUENTE_FINANC | VARCHAR | Fuente de financiamiento (1=Recursos Ordinarios, 2=Recaudados, etc.). |
FUNCION | VARCHAR | Función presupuestal (ej "22. EDUCACION", "20. SALUD"). |
CATEGORIA_GASTO | VARCHAR | 5 GASTO CORRIENTE · 6 GASTO DE CAPITAL · 7 SERVICIO DE DEUDA. |
GENERICA | VARCHAR | Genérica del clasificador (ej "21" = Personal). Sin puntos al filtrar. |
MTO_PIA | DOUBLE | Presupuesto Inicial de Apertura (S/). |
MTO_PIM | DOUBLE | Presupuesto Institucional Modificado (S/) — techo vigente. |
DEVENGADO_ | DOUBLE | Devengado acumulado del año (S/). |
MTO_DEVENGA_01..12 | DOUBLE | 12 columnas — devengado mensual por mes calendario. |
💡 Pista: SECTOR usa formato "NN: NOMBRE" (dos puntos)
mientras que PLIEGO y DEPARTAMENTO_META usan
"NN. NOMBRE" (punto). Siempre filtrá con LIKE 'NN%' para evitar errores por formato.
📖 OpenAPI interactivo
Explorá cada endpoint con un Swagger UI live, o descargate la spec JSON para llevarla a Postman, Insomnia, tu generador de código o tu LLM favorito.
¿Construyendo algo con esto?
Nos encantaría verlo. Escribinos a soporte@gestionpublicaperu.com.pe .