Quick start
setupConectar tu app al backend en 30 segundos.
Variables de entorno
NEXT_PUBLIC_API_URL=https://nomad-centinela-api.vercel.app
Smoke test
curl -s https://nomad-centinela-api.vercel.app/api/health | jq
Endpoints disponibles
| Method | Path | Descripcion |
|---|---|---|
| GET | /api/health | Salud del sistema |
| GET | /api/institutions | Lista de instituciones monitoreadas |
| GET | /api/events | Eventos de exposicion |
| GET | /api/events/:id | Detalle de un evento |
| POST | /api/citizen/check | Verificar si un hash esta expuesto |
| GET | /api/playbooks | Lista de playbooks |
| GET | /api/playbooks/search?q= | Buscar playbooks (FTS) |
| GET | /api/playbooks/:slug | Contenido de un playbook |
| POST | /api/agent/triage | Ejecutar agente Triage |
| POST | /api/agent/investigate | Ejecutar agente Investigator |
| POST | /api/agent/pipeline | Triage + Investigator + HITL en una llamada |
| POST | /api/agent/chat | Chat ciudadano (respuesta diferida JSON) |
| POST | /api/webhooks/make/ingest | Ingesta desde Make.com |
API explorer
interactiveEjecuta cada endpoint en tiempo real contra produccion.
/api/healthVerifica que Supabase, MiniMax y el webhook de Make estan operativos.
/api/institutionsLista todas las instituciones que NOMAD monitorea con conteo de eventos.
/api/eventsLista eventos de exposicion. Filtra por status o severity.
/api/events/:idDetalle completo de un evento: traces de agentes, reviews HITL, payload.
/api/citizen/checkVerifica si un prefijo de hash aparece en la base de datos de breach. Solo k-anonymity: nunca se expone el hash completo.
/api/playbooks/searchBusqueda en lenguaje natural sobre playbooks de respuesta. Usa pgvector FTS.
/api/playbooks/:slugContenido completo de un playbook en Markdown.
/api/agent/triageClasifica la severidad de un evento usando MiniMax. Si MiniMax falla, devuelve resultado mock.
/api/agent/investigateBusca fuentes OSINT para verificar el evento. Usa MiniMax.
/api/agent/pipelineEjecuta Triage + Investigator + estado HITL en una sola llamada atomica.
/api/webhooks/make/ingestIngesta evento sintetico desde Make.com. El secret ya viene configurado.
Integration recipes
cookbookPatrones reales para conectar frontend y mobile al backend.
Recipe A — Next.js Server Component
Datos en el servidor (RSC). Ideal para pages sin interactividad en tiempo real.
// app/dashboard/page.tsx (Next.js 15 Server Component)
import { fetchEvents } from '@/lib/api';
export default async function DashboardPage() {
const { data: events } = await fetchEvents({ status: 'pending_review' });
return (
<ul>
{events.map((e) => (
<li key={e.id}>
<span className={severityColor(e.severity)}>{e.severity}</span>
{' '}{e.title}
</li>
))}
</ul>
);
}Recipe B — Next.js Client Component
Interactividad. Ejecuta agentes, polling, streaming de chat.
'use client';
import { useState } from 'react';
import { runTriage, runInvestigate } from '@/lib/api';
export function AgentPanel({ eventId }: { eventId: string }) {
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<unknown>(null);
async function handleTriage() {
setLoading(true);
try {
const json = await runTriage(eventId);
setResult(json.triage);
} finally {
setLoading(false);
}
}
return (
<div>
<button onClick={handleTriage} disabled={loading}>
{loading ? 'Ejecutando…' : 'Ejecutar Triage'}
</button>
{result && <pre>{JSON.stringify(result, null, 2)}</pre>}
</div>
);
}Recipe C — Flutter con http
Equivalente movil del fetch. Compatible with emulator (http://10.0.2.2:3001 for Android).
import 'dart:convert';
import 'package:http/http.dart' as http;
class NomadApi {
static const apiBase = String.fromEnvironment(
'API_BASE',
defaultValue: 'https://nomad-centinela-api.vercel.app',
);
static Future<List<dynamic>> getEvents({String? status}) async {
final qs = status != null ? '?status=$status' : '';
final resp = await http.get(
Uri.parse('$apiBase/api/events$qs'),
headers: {'Content-Type': 'application/json'},
);
final json = jsonDecode(resp.body);
return json['data'] as List<dynamic>;
}
static Future<Map<String, dynamic>> checkCitizen(String hashPrefix) async {
final resp = await http.post(
Uri.parse('$apiBase/api/citizen/check'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'hash_prefix': hashPrefix}),
);
return jsonDecode(resp.body) as Map<String, dynamic>;
}
}Recipe D — SSE streaming (limitacion en Vercel)
POST /api/agent/chat soporta streaming SSE en desarrollo local. En Vercel (serverless), el stream se convierte a JSON por incompatibilidad del runtime. La UI del chat ya tiene fallback JSON que funciona indistintamente.
const res = await fetch(`${API_URL}/api/agent/chat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages: [{ role: 'user', content: '¿Estoy expuesto?' }] }),
});
const { messages } = await res.json(); // JSON normal, no stream
const reply = messages[messages.length - 1].content;Make.com scenarios
makeLos webhooks activos en tu cuenta. Puedes dispararlos manualmente o conectar fuentes OSINT.
NOMAD Centinela - Ingesta OSINT sintética
id 5087018Trigger: webhook personalizado. Envía datos al backend via POST /api/webhooks/make/ingest.
https://hook.us2.make.com/vz2nrhdwcfdh64iz7igbbj0iirem4wx5NOMAD Centinela - HITL email
id 5087019Trigger: webhook personalizado. Envía email a z648s.7bt@gmail.com cuando el backend detecta pending_review.
https://hook.us2.make.com/1f2bkj72aiqxb4abellrbn3ulkwcbttvFTS vs Vector — RAG semantico
ragDos modos de busqueda en playbooks: Full-Text Search (FTS) y busqueda vectorial (pgvector). Cambia el modo y observa la diferencia en los rankings.
npm run embed:playbooks corrido. Sin embeddings, Vector cae automaticamente a FTS.