QUICK FACTS
…application/jsonAuthorization: Bearer <key> header./api/v1/…).{ "error": "<message>" } with HTTP 4xx/5xx status.ENDPOINTS
Pharma RWE view — disease burden posteriors, treatment cascade indicators, daily HIV trend, all combined with published WHO/UNAIDS priors. Recommended polling cadence: hourly.
Example request
curl https://.../api/insights/pharma
Sample response (truncated)
{
"view": "pharma_rwe",
"generated_at": "2026-04-26T17:42:11.039Z",
"coverage": {
"country": "Lesotho",
"population": 2100000,
"observed_cases_window_30d": 117
},
"burden_projection": {
"by_topic": {
"hiv": {
"observed": 42,
"projection": {
"posteriorMean": 0.2295,
"lower": 0.1718,
"upper": 0.2872,
"effectiveSampleSize": 203
}
},
"tb": {
"observed": 14,
"projection": {
"point_estimate_per_100k": 650,
"note": "TB rate projection requires CHW-catchment population denominator..."
}
}
}
},
"projections": {
"hiv": [ /* array of cascade indicator cards — see /api/insights/pharma */ ],
"tb": [ /* ... */ ],
"other": [ /* ... */ ]
},
"methodology_url": "/methodology"
}
Strategic view for multilateral observers (WHO, Africa CDC, Gates Foundation, bilateral donors). Country-level posteriors, severity distribution, district signals, and (when multi-country) regional comparison.
Example request
curl https://.../api/insights/public-health
Sample response shape
{
"view": "who_surveillance",
"generated_at": "...",
"coverage": { ... },
"severity_distribution": [
{ "severity": "routine", "count": 75 },
{ "severity": "urgent", "count": 28 },
{ "severity": "emergency", "count": 14 }
],
"by_district": [ { "district": "Maseru", "count": 32 }, ... ],
"burden_projection": { ... },
"projections": { "hiv": [...], "tb": [...], "mnch": [...], "other": [...] },
"outbreak_signals_note": "...",
"methodology_url": "/methodology"
}
Operational view for the licensing ministry — their own CHW network's activity. Topic distribution, severity flags, district coverage. Plus Bayesian projections for cross-reference.
Sample response shape
{
"view": "ministry",
"by_topic": [ { "topic": "HIV", "count": 42 }, ... ],
"severity_distribution": [ ... ],
"by_district": [ ... ],
"projections": { ... }
}
Audit feed. Every interaction logged with anonymized identifiers, retrieved sources, safety outcome, and latency. Useful for compliance, evaluation, and model-behavior monitoring.
| Param | Type | Description |
|---|---|---|
| limit | integer | Max conversations returned. Default 50, max 200. |
Sample response shape
{
"summary": { "total": 117, "last24h": 8, "fallback": 12, "refused": 9 },
"conversations": [
{
"id": 117,
"created_at": "2026-04-26 17:32:11",
"from_number": "***0100",
"input_type": "voice",
"transcribed_text": "...",
"safety_outcome": "allowed",
"retrieved_sources": [
{ "source": "ART Defaulter Pathway", "section": "§ 4", "score": 0.62 }
],
"response_text": "...",
"latency_ms": 4340
}
]
}
Liveness check. Used by orchestration (Render, Fly.io) and external monitors.
{
"ok": true,
"service": "luma",
"version": "0.1.0",
"timestamp": "2026-04-26T17:42:11.039Z"
}
SAFETY OUTCOMES — DECODER
Every interaction in /log.json carries a safety_outcome tag. Consumers should filter on these for compliance dashboards and content audits.
| Outcome | Meaning |
|---|---|
| allowed | Query passed safety, retrieval found a high-confidence corpus match (≥0.45), Claude responded with cited protocol section. |
| allowed_with_warning | Allowed but the post-LLM check noted something to surface — e.g., missing citation pattern in the response. |
| fallback_general_knowledge | Query passed safety but had no good corpus match. Claude answered from general WHO knowledge with the visible "⚠️ Not from your ministry protocols" disclaimer. |
| clinical_advice_requested | Hard refusal: query asked for dosing, diagnosis, or drug interactions. |
| out_of_scope_topic | Hard refusal: topic outside CHW workflow (diabetes, surgery, etc.). |
| trivial_input | Greeting / acknowledgement; no LLM call made. |
| empty_input | Empty message body. |
| input_too_long | Message exceeded length limit (2000 chars). |
| transcription_failed | Voice memo failed to transcribe; user prompted to retry as text. |
| unsafe_dose_recommendation | Post-LLM check detected and scrubbed an unsafe dose recommendation. Should never appear in production with current safety design. |
POSTERIOR FIELDS — DECODER
Each projection card returned by the insights endpoints follows the same schema:
| Field | Type | Description |
|---|---|---|
| label | string | Human-readable indicator name. |
| prior.mean | number 0–1 | Published prior (e.g., 0.228 for HIV adult prevalence). |
| prior.source | string | Citation for the prior. |
| prior.effective_n | integer | Effective sample size — controls how strongly the prior anchors the posterior. Higher = stronger. |
| observed.successes | integer | Count of CHW interactions matching the indicator's criterion. |
| observed.trials | integer | Denominator for the share calculation. |
| observed.share | number 0–1 | successes / trials. |
| posterior.mean | number 0–1 | Bayesian posterior estimate. |
| posterior.lower_95ci | number 0–1 | Lower bound of 95% CI (normal approximation to Beta). |
| posterior.upper_95ci | number 0–1 | Upper bound of 95% CI. |
| posterior.effective_sample_size | integer | Combined α + β of the posterior Beta distribution. |
| data_weight_pct | number 0–100 | How much the data has shifted the posterior away from the prior. 0 = pure prior, 100 = pure observation. |
| confidence | string | One of: no_observed_data, very_small_sample, small_sample, moderate_sample, large_sample. |
CLIENT EXAMPLES
Python
import requests
BASE = "https://your-luma-deployment.example.com"
# Pull pharma view
r = requests.get(f"{BASE}/api/insights/pharma")
data = r.json()
# Iterate cascade indicators
for indicator in data["projections"]["hiv"]:
label = indicator["label"]
post = indicator["posterior"]
ci = f"{post['lower_95ci']:.1%}–{post['upper_95ci']:.1%}"
print(f"{label}: {post['mean']:.2%} (95% CI {ci})")
R
library(httr)
library(jsonlite)
base <- "https://your-luma-deployment.example.com"
res <- GET(paste0(base, "/api/insights/pharma"))
data <- content(res, as = "parsed", simplifyVector = TRUE)
# HIV cascade indicators as data.frame
hiv <- data$projections$hiv
print(hiv[, c("label", "posterior.mean", "posterior.lower_95ci",
"posterior.upper_95ci", "confidence")])
Pipe to a CSV
curl -s https://your-luma-deployment.example.com/api/insights/pharma \
| jq '.projections.hiv[] | {label, prior: .prior.mean, posterior: .posterior.mean,
ci_lower: .posterior.lower_95ci, ci_upper: .posterior.upper_95ci, confidence}' \
| jq -s '. | (.[0] | keys_unsorted) as $keys | $keys, map([.[ $keys[] ]])[] | @csv' \
-r > hiv_cascade.csv
ROADMAP
Production hardening (Series A scope).
- API key authentication with per-key rate limits
- Webhook subscriptions for material posterior changes (e.g., when data weight crosses 25% threshold)
- Multi-country aggregation endpoints (
/api/insights/region/sa) - CDISC-compliant exports for FDA/EMA RWE submissions
- Versioned API at
/api/v1/…with stability guarantees - Python and R SDKs (auto-generated from OpenAPI spec)
- 99.9% uptime SLA
STATUS
luma is in BETA. The API surface is stable enough to integrate against, but expect:
- No SLA. Best-effort uptime via Render or Fly.io infrastructure.
- Schema additions are non-breaking; field renames will trigger a major version bump.
- Rate-limits are not enforced but please be courteous (~1 req/sec sustained).
- Production access requires direct contact via sebastian.r.buck@gmail.com.