Platform para sa Developer

Mga API at Widget

Mag-embed ng live na metrics ng Espiritu at Tubig sa anumang site, o direktang kumonekta sa aming REST API at SSE stream. Hindi kailangan ng authentication para sa mga pampublikong read endpoint.

Mabilis na pagsisimula

Ang pinakamabilis na paraan para ipakita ang data ng 238 Global sa iyong site ay iframe o ang aming drop-in na embed.js script. Parehong naglo-load ang mga ito ng mga nakahandang widget mula sa mga route na /embed/* na may kaunting chrome.

Live na preview — Metrics widget

Mag-embed ng mga widget

May tatlong uri ng widget: metrics (4 na counter), feed (nag-i-scroll na listahan ng aktibidad), at globe (interactive na 3-D globe na may mga marker ng live na ulat).

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

Mga attribute

data-238
Uri ng widget: metrics, feed, o globe
data-base
Base URL sa script tag (para sa mga cross-origin embed)
data-src
Ganap na palitan ang src ng iframe
data-width / data-height
Mga sukat (default: 100% × 120 o 320)

REST API

Nagbabalik ng JSON ang lahat ng pampublikong read endpoint. Base path: /api/v1

GET/api/v1/metrics

Pinagsama-samang mga counter para sa pagkapuno ng Espiritu, bautismo sa tubig, pinagsamang event, at mga kabuuan — kasama ang mga bilang ngayong araw.

{
  "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

Mga bagong aprubadong ulat. Mga query param: limit (max 100), since (ISO datetime).

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

Server-Sent Events stream. Kapag kumonekta at kada 5 segundo, dalawang pinangalanang event ang ipinapadala:

  • metricsMga pinagsama-samang counter na kapareho ng GET /api/v1/metrics.
  • reportsObject { reports: [...] } — ang 20 pinakabagong aprubadong ulat.
  • errorIpinapadala lamang kapag pumalya ang server-side tick; { 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
});

Pag-authenticate

Gumagana ang mga pampublikong read endpoint nang walang credential. Para sa mas mataas na rate limit, isama ang iyong API key bilang Bearer token sa Authorization header.

Request na may API key
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>

Ang team ng 238 Global ang nagbibigay ng mga API key. Makipag-ugnayan sa [email protected] para humiling ng partner key.

Mga rate limit

Inilalapat ang mga rate limit kada IP para sa request na walang authentication, o kada API key para sa request na authenticated. Kapag lumampas sa limit, ibinabalik ang 429 Too Many Requests.

Pampubliko
60 / min
Mga read na walang authentication (kada IP)
Partner
1,000 / min
Kailangan ang Bearer API key
Enterprise
Walang limit
Makipag-ugnayan sa amin para sa access

Mga halimbawa

Kunin ang metrics
const res = await fetch('https://238global.com/api/v1/metrics');
const { total, spiritToday } = await res.json();
document.getElementById('count').textContent = total.toLocaleString();
Kunin ang mga ulat kada 30 segundo
async function poll() {
  const res = await fetch('/api/v1/reports?limit=5');
  const { reports } = await res.json();
  renderFeed(reports);
}
setInterval(poll, 30_000);
poll();

Mga webhook

Maaaring mag-subscribe ang mga partner key sa mga real-time event webhook. Kapag may event, nagpo-POST ang 238 Global ng signed JSON payload sa iyong endpoint. Irehistro ang mga subscription sa pamamagitan ng API.

Mga suportadong event

report.created
Ipinapadala kapag na-publish ang isang ulat. Nasa payload ang buong report object.
metrics.updated
Ipinapadala matapos aprubahan ang bawat ulat, kasama ang na-update na pinagsama-samang metrics.
Magrehistro ng webhook subscription
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"
  }
}
Ilista ang mga subscription
GET /api/v1/webhooks
Authorization: Bearer 238_<your-api-key>
Mag-delete ng subscription
DELETE /api/v1/webhooks?id=sub_…
Authorization: Bearer 238_<your-api-key>

Pag-verify ng mga signature

Kasama sa bawat webhook request ang X-238-Signature header. Ang value ay sha256=<hex> na kinukuwenta bilang HMAC-SHA256 ng raw request body gamit ang secret ng iyong subscription.

Node.js — i-verify ang signature
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);
});

Istruktura ng webhook payload

{
  "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"
  }
}