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).

HTML — iframe
<iframe
  src="https://238global.com/embed/metrics"
  width="100%"
  height="120"
  frameborder="0"
  title="238 Global Metrics"
></iframe>
HTML — embed.js (JavaScript puro)
<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>
React
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

GET/api/v1/metrics

Contadores 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"
}
GET/api/v1/reports

Informes 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"
    }
  ]
}
GET/api/v1/streamSSE

Flujo 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 }.
JavaScript — EventSource
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.

Solicitud con clave API
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.

Público
60 / min
Lecturas sin autenticar (por IP)
Socio
1,000 / min
Requiere una clave API Bearer
Empresarial
Sin límite
Contáctanos para solicitar acceso

Ejemplos

Obtener métricas
const res = await fetch('https://238global.com/api/v1/metrics');
const { total, spiritToday } = await res.json();
document.getElementById('count').textContent = total.toLocaleString();
Consultar informes cada 30 s
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.
Registrar una suscripción a webhooks
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"
  }
}
Enumerar suscripciones
GET /api/v1/webhooks
Authorization: Bearer 238_<your-api-key>
Eliminar una suscripción
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.

Node.js — verificar firma
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"
  }
}