Plataforma para desarrolladores
APIs y widgets
Incorpora métricas en vivo de Espíritu y agua en cualquier sitio o integra directamente nuestra API REST y el flujo SSE. Los endpoints públicos de lectura no requieren autenticación.
Inicio rápido
La forma más rápida de mostrar datos de 238 Global en tu sitio es mediante un iframe o nuestro script embed.js listo para usar. Ambos cargan widgets prediseñados desde las rutas /embed/* con una interfaz mínima.
Vista previa en vivo — Widget de métricas
Incorporar widgets
Hay tres tipos de widgets: métricas (4 contadores), actividad (lista desplazable) y globo (globo 3D interactivo con marcadores de informes en vivo).
<iframe
src="https://238global.com/embed/metrics"
width="100%"
height="120"
frameborder="0"
title="238 Global Metrics"
></iframe><script src="https://238global.com/embed.js" data-base="https://238global.com"></script>
<div data-238="metrics" data-width="100%" data-height="120"></div>
<div data-238="feed" data-width="100%" data-height="320"></div>
<div data-238="globe" data-width="100%" data-height="400"></div>function MetricsWidget() {
return (
<iframe
src="/embed/metrics"
width="100%"
height="120"
style={{ border: 0 }}
title="238 Global Metrics"
/>
);
}Atributos
- data-238
- Tipo de widget: metrics, feed o globe
- data-base
- URL base en la etiqueta del script (para incorporaciones entre orígenes)
- data-src
- Reemplaza por completo el valor src del iframe
- data-width / data-height
- Dimensiones (valores predeterminados: 100% × 120 o 320)
REST API
Todos los endpoints públicos de lectura devuelven JSON. Ruta base: /api/v1
/api/v1/metricsContadores agregados de llenuras del Espíritu, bautismos en agua, eventos combinados y totales, incluidos los recuentos de hoy.
{
"spirit": 14832,
"water": 9451,
"both": 7206,
"total": 31489,
"spiritToday": 127,
"waterToday": 84,
"bothToday": 63,
"totalToday": 274,
"countries": 42,
"cities": 186,
"updatedAt": "2026-07-09T18:00:00.000Z"
}/api/v1/reportsInformes aprobados recientes. Parámetros de consulta: limit (máx. 100), since (fecha y hora ISO).
GET /api/v1/reports?limit=10&since=2026-07-01T00:00:00Z
{
"reports": [
{
"id": "clx…",
"city": "Lagos",
"country": "Nigeria",
"peopleCount": 23,
"type": "spirit",
"createdAt": "2026-07-09T17:45:00.000Z"
}
]
}/api/v1/streamSSEFlujo de eventos enviados por el servidor. Al conectarse y cada 5 segundos, se emiten dos eventos con nombre:
metricsContadores agregados idénticos a GET /api/v1/metrics.reportsObjeto { reports: [...] } con los 20 informes aprobados más recientes.errorSolo se emite cuando falla una ejecución del servidor; { message: string }.
const es = new EventSource('/api/v1/stream');
es.addEventListener('metrics', (e) => {
const metrics = JSON.parse(e.data);
console.log('Total:', metrics.total);
});
es.addEventListener('reports', (e) => {
const { reports } = JSON.parse(e.data);
console.log('Latest city:', reports[0]?.city);
});
es.addEventListener('error', (e) => {
// native EventSource error (connection lost) — reconnects automatically
// named 'error' events from server indicate a tick failure
});Autenticación
Los endpoints públicos de lectura funcionan sin credenciales. Para acceder a límites de solicitudes más altos, incluye tu clave API como token Bearer en el encabezado Authorization.
GET /api/v1/metrics HTTP/1.1
Authorization: Bearer 238_<your-api-key>
GET /api/v1/reports?limit=100 HTTP/1.1
Authorization: Bearer 238_<your-api-key>El equipo de 238 Global emite las claves API. Escribe a [email protected] para solicitar una clave de socio.
Límites de solicitudes
Los límites se aplican por IP a las solicitudes sin autenticar y por clave API a las solicitudes autenticadas. Superar el límite devuelve 429 Too Many Requests.
Ejemplos
const res = await fetch('https://238global.com/api/v1/metrics');
const { total, spiritToday } = await res.json();
document.getElementById('count').textContent = total.toLocaleString();async function poll() {
const res = await fetch('/api/v1/reports?limit=5');
const { reports } = await res.json();
renderFeed(reports);
}
setInterval(poll, 30_000);
poll();Webhooks
Las claves de socios pueden suscribirse a webhooks de eventos en tiempo real. Cuando se activa un evento, 238 Global envía mediante POST un contenido JSON firmado a tu endpoint. Registra las suscripciones mediante la API.
Eventos compatibles
- report.created
- Se activa cuando se publica un informe. El contenido incluye el objeto completo del informe.
- metrics.updated
- Se activa después de aprobar cada informe e incluye las métricas agregadas actualizadas.
POST /api/v1/webhooks
Authorization: Bearer 238_<your-api-key>
Content-Type: application/json
{
"url": "https://yourapp.example.com/webhooks/238",
"events": ["report.created", "metrics.updated"]
}
// Response — save the secret, shown once
{
"subscription": {
"id": "sub_…",
"url": "https://yourapp.example.com/webhooks/238",
"events": ["report.created", "metrics.updated"],
"secret": "abc123…",
"createdAt": "2026-07-09T22:00:00.000Z"
}
}GET /api/v1/webhooks
Authorization: Bearer 238_<your-api-key>DELETE /api/v1/webhooks?id=sub_…
Authorization: Bearer 238_<your-api-key>Verificación de firmas
Cada solicitud de webhook incluye un encabezado X-238-Signature. El valor es sha256=<hex>, calculado como HMAC-SHA256 a partir del cuerpo original de la solicitud y el secreto de tu suscripción.
import { createHmac, timingSafeEqual } from 'crypto';
function verifyWebhook(body: string, header: string, secret: string): boolean {
const expected = 'sha256=' + createHmac('sha256', secret).update(body).digest('hex');
return timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}
// Express / Next.js route handler
app.post('/webhooks/238', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-238-signature'] as string;
if (!verifyWebhook(req.body.toString(), sig, process.env.WEBHOOK_SECRET!)) {
return res.status(401).send('Invalid signature');
}
const { event, data } = JSON.parse(req.body.toString());
console.log('Received event:', event, data);
res.sendStatus(200);
});Estructura del contenido del webhook
{
"event": "report.created",
"timestamp": "2026-07-09T22:00:00.000Z",
"data": {
"id": "clx…",
"city": "Lagos",
"country": "Nigeria",
"peopleCount": 23,
"type": "spirit",
"status": "APPROVED",
"createdAt": "2026-07-09T22:00:00.000Z"
}
}