🚧 The EHSPI live link will be updated shortly. In the meantime, reach us at ops@exposomic.ai
Platform & API

Environmental health intelligence,
delivered as infrastructure.

One API call returns real-time environmental context, condition-specific risk scoring, and peer-reviewed citations — ready to embed in any digital health product, insurance workflow, or population health programme.

One endpoint. Full intelligence.

POST a condition and location. Receive risk level, environmental signals, synthesis paragraph, inline citations, and EHSPI score. No assembly required.

🔬
Evidence-grounded, not estimated

Every response cites the peer-reviewed papers that support it. 350,000+ articles. Semantic retrieval. LLM gate for relevance. Not a rule-based lookup.

🌍
Real-time. 20 cities. 7 data sources.

Google AQ, Weather, and Pollen APIs — 7 signal types per tile, updated hourly. 22 global cities seeded. Custom tile support available.

🔒
Anonymous by design

No PII required or stored. Anonymous session tokens only. No user profiles. GDPR-compatible architecture. Pass a location string, get intelligence back.

Four-layer pipeline from raw signal
to cited intelligence

Each layer is independently cached and observable. The pipeline runs end-to-end in under 4 seconds at P50. All layers write structured logs to Cloud Logging with a shared X-Request-ID for full traceability.

1
Environmental data ingestion — Layer 1 (raw cache)
7 Google Environmental API calls per tile per refresh cycle. AQ current + forecast + history. Weather current + forecast + history. Pollen forecast. Raw JSON stored in env_hourly_cache (48h TTL) and pollen_daily_cache (5d TTL). High-priority tiles refresh every 60 min; standard tiles every 180 min.
PostgreSQL · Cloud Run Job
2
Feature computation — Layer 2 (env_features_window)
Raw signals transformed into 24h and 72h window features: pressure_delta_mb, pressure_volatility_mb, pm25_mean, aqi_hours_unhealthy, heat_index_mean, overnight_hot_hours, pollen_exposure_load, and 14 more. All features normalised across the monitored tile set for EHSPI scoring.
env_features_compute.py
3
Evidence retrieval pipeline — Layer 3 (RAG) Patent pending
5-stage pipeline: (1) Query planner generates condition-specific subqueries. (2) pgvector HNSW index over 350,000+ BAAI/bge-base-en-v1.5 embeddings (768 dims). (3) BM25 + semantic ranker. (4) LLM relevance gate — filters hallucinated or weak matches. (5) Top papers passed to synthesis with environmental context.
pgvector · OpenAI gpt-4.1-mini
4
Intelligence synthesis — Layer 4 (structured output)
GPT-4.1 mini generates structured JSON: risk_level, synthesis paragraph, condition-specific recommendations (3–5), uncertainty notes, and inline citations. Enrichment context (subtype, triggers, medication, lag) modulates the synthesis prompt and output focus. Response logged to insight_requests with full observability fields.
FastAPI · Cloud Run
Performance targets
< 4s
P50 latency
Full pipeline
< 9s
P95 latency
Synthesis included
60 min
Cache TTL
High-priority tiles
Weekly
Corpus update
Monday 03:00 UTC

Complete API specification

All endpoints require the X-Api-Key header except GET /health. Contact us to request credentials.

Authentication

Pass your API key in the X-Api-Key request header. Keys are issued per integration. Rate limiting is applied per key. There is no OAuth flow — the API is stateless.

X-Api-Key: your-api-key-here

Content type & encoding

All POST bodies are application/json. All responses are application/json. Responses are UTF-8 encoded. Timestamps are ISO 8601 UTC.

Content-Type: application/json
Accept: application/json
Core intelligence
POST /v1/insight 🔑 X-Api-Key Primary intelligence endpoint. Returns risk level, environmental breakdown, synthesis, citations.

The core endpoint. Submit a condition sensitivity and location; receive a complete environmental health intelligence response including risk level, environmental signal breakdown, a synthesis paragraph grounded in peer-reviewed evidence, inline citations, EHSPI score, and structured recommendations. Optional enrichment fields personalise the synthesis to the user's specific subtype, triggers, and medication.

Request parameters
Field Type Required Description
condition string Required Sensitivity key. One of: migraine · respiratory · cardiovascular · sleep · allergies
location string Required Free-text location string — city name, city + country, or coordinates. Resolved to the nearest seeded tile. Examples: "London, UK" · "Delhi" · "Dubai, UAE"
window_hours integer Optional Time window in hours. One of: 6 · 24 · 72. Default: 24
direction string Optional Temporal direction. "future" (forecast) or "past" (historical). Default: "future"
activity string Optional User's activity context. One of: "mostly_indoors" · "mixed" · "outdoor_exercise". Modulates exposure weighting in synthesis. Default: "mostly_indoors"
enrichment object Optional Personalisation object. See enrichment fields below. When provided, the synthesis is tailored to the user's specific subtype, triggers, and medication context.
Enrichment object fields
Field Type Description
condition_subtype string Specific subtype within the sensitivity. E.g. "chronic migraine", "asthma", "hay fever"
onset_pattern string Typical onset pattern. E.g. "gradual onset over hours", "sudden onset"
known_triggers string[] Array of known trigger strings. E.g. ["weather changes", "stress", "bright light"]
trigger_onset_lag_hours number Typical hours between trigger exposure and symptom onset. Options: 0.25, 0.5, 1.0, 1.5, 3.0, 6.0, 12.0, 24.0, 48.0, 72.0
medication string Current relevant medication. E.g. "sumatriptan", "salbutamol inhaler", "cetirizine"
comorbidities string[] Other relevant conditions. E.g. ["anxiety", "hypertension"]
Example request
"condition": "migraine", "location": "London, UK", "window_hours": 24, "direction": "future", "activity": "mostly_indoors", "enrichment": "condition_subtype": "chronic migraine", "onset_pattern": "gradual onset over hours", "known_triggers": [ "weather changes", "barometric pressure drops" ], "trigger_onset_lag_hours": 3.0, "medication": "sumatriptan"
Example response (abbreviated)
"request_id": "req_abc123", "condition": "migraine", "location": "London, UK", "risk_level": "Moderate", "summary": "Rapid frontal passage with a 6.2 mb pressure drop...", "recommendations": [ "Consider preventative review if sumatriptan available", "Pressure volatility remains elevated for 72h" ], "environment": "pressure_delta_mb": -6.2, "pressure_volatility_mb": 8.4, "heat_index_mean": 16.3, "ehspi_composite": 62 , "top_matches": [ "title": "Barometric pressure and migraine...", "authors": "Prince et al.", "year": 2017, "fit_level": "High" ], "uncertainty_notes": [ "Tile data updated 47 min ago" ]
EHSPI — Environmental Health Sensitivity Performance Index
GET /v1/ehspi 🔑 X-Api-Key EHSPI scores for all monitored cities. Cache-first, updated nightly.

Returns EHSPI composite and per-sensitivity scores for monitored cities. Cache-first — responses served from ehspi_scores table, refreshed nightly at 02:00 UTC. Specify sensitivity=all to retrieve all five sensitivity dimensions in one call.

Query parameters
ParameterTypeDefaultDescription
sensitivity string all Sensitivity to return. One of: all · migraine · respiratory · cardiovascular · sleep · allergies
mode string lifetime Scoring window. lifetime · 30d · 90d. Lifetime uses all available history; rolling modes use recent data only.
tile_id string Optional. Filter to a specific tile. Format: r2:{lat2dp},{lon2dp}. E.g. r2:51.51,-0.13 for London.
Example request
GET /v1/ehspi?sensitivity=all&mode=lifetime # Filter to a specific city: GET /v1/ehspi?sensitivity=migraine&mode=30d&tile_id=r2:51.51,-0.13
Example response
"mode": "lifetime", "computed_date": "2026-04-07", "cache_hit": true, "tiles": 22, "results": [ "tile_id": "r2:51.51,-0.13", "location_name": "London, UK", "ehspi_composite": 62, "ehspi_migraine": 58, "ehspi_respiratory": 67, "ehspi_cardiovascular": 71, "ehspi_sleep": 65, "ehspi_allergies": 48, "confidence": "High", "history_days": 94 ]
GET /v1/ehspi/history 🔑 X-Api-Key Daily EHSPI score history for a tile — powers trend charts.

Returns a daily time series of EHSPI composite and per-sensitivity scores for a specific tile. Use to power trend visualisations or longitudinal analysis. Data available from the tile's first ingestion date.

Query parameters
ParameterTypeRequiredDescription
tile_id string Required Tile identifier. Format: r2:{lat2dp},{lon2dp}
sensitivity string Optional Filter to a specific sensitivity. Default: returns all five plus composite.
days integer Optional Number of days of history to return. Default: 90. Max: 365.
GET /v1/trends 🔑 X-Api-Key Environmental signal trend series for a tile and sensitivity.

Returns a time series of raw environmental signal values (not EHSPI scores) for a tile and sensitivity — useful for displaying individual signal trends (e.g. PM2.5 over 30 days, or pressure volatility over 7 days) in a partner dashboard.

Query parameters
ParameterTypeRequiredDescription
sensitivity string Required Sensitivity key
tile_id string Required Tile identifier
window string Optional Time window. 7d · 30d · 90d. Default: 30d
Alerts & push notifications
POST /api/alert/subscribe 🔑 X-Api-Key Subscribe a device to push alerts when risk threshold is met.

Registers a Web Push subscription for a device. When the alert monitor job (runs hourly) detects that the risk level for the subscribed condition and location meets or exceeds the threshold, a Web Push notification is delivered. No account required — subscriptions are tied to device and session token only. Subscriptions expire after 30 days of inactivity.

Request body
FieldTypeRequiredDescription
subscription object Required Web Push subscription object from PushManager.subscribe(). Contains endpoint, keys.p256dh, keys.auth
condition string Required Sensitivity key to monitor
location string Required Location string to monitor
threshold string Optional "High" (notify only on High risk) or "Moderate" (notify on Moderate or above). Default: "High"
session_token string Optional Anonymous UUID identifying the device session. Used for deduplication and unsubscribe. Generated client-side — not linked to any user identity.
DELETE /api/alert/unsubscribe 🔑 X-Api-Key Remove a push alert subscription by session token or endpoint.

Removes an active push subscription. Pass either the session_token or the push endpoint URL to identify the subscription to remove. Immediate effect — the hourly alert monitor will not fire for this device on the next run.

Request body
FieldTypeDescription
session_token string Anonymous session UUID. One of session_token or endpoint required.
endpoint string Web Push endpoint URL from the original subscription object.
Feedback & system
POST /api/feedback 🔑 X-Api-Key Submit structured user feedback on an insight response.

Captures structured feedback on a specific insight response. Feedback is linked to the original request_id for correlation with the full pipeline context. Anonymous — no PII required. All fields optional except helpful.

Request body
FieldTypeRequiredDescription
helpful boolean Required true = thumbs up. false = thumbs down.
request_id string Optional The request_id from the insight response this feedback relates to.
feedback_categories string[] Optional Issue chips (thumbs-down): risk_level_wrong · data_incorrect · recommendations_irrelevant · research_irrelevant · missing_info · hard_to_understand
feedback_positive_aspects string[] Optional Positive chips (thumbs-up): risk_warning · recommendations · env_breakdown · research_evidence · pollen_data
risk_accuracy string Optional User's assessment: accurate · too_high · too_low · not_yet_experienced
improvement_text string Optional Free-text comment. Max 200 characters server-side.
session_token string Optional Anonymous UUID. Used for device-level correlation only. Not linked to any user identity.
GET /health No auth Health check. Returns 200 OK when the API is operational.
Request
GET /health
Response
"status": "ok"
🔒

Privacy architecture Patent pending

The API requires no user accounts, no PII, and no persistent user profiles. Location strings are resolved to the nearest tile and are not stored beyond the request lifecycle. The only persistent identifier is an optional anonymous session_token (UUID) generated client-side — used solely for alert subscription deduplication and feedback correlation. It cannot be linked to any individual. All data processing is governed by the exposomic.ai privacy policy. GDPR-compatible by design.

Three integration patterns

Digital health app
Condition management app

Add an environmental risk check to your daily check-in flow. A migraine app calls /v1/insight with the user's home location each morning. The response drives a risk badge and a cited explanation in the app. No PII sent — just a location string and condition key.

POST /v1/insight Push alerts No user account
Discuss this integration
Health insurer
Population environmental risk monitoring

Monitor environmental health risk across a member population by city cohort. Call /v1/ehspi nightly to pull composite scores for all 20 monitored cities. Feed into underwriting models or proactive member outreach when EHSPI drops below threshold in high-density cities.

GET /v1/ehspi GET /v1/ehspi/history 20 cities
Discuss this integration
Research institution
Longitudinal environmental exposure study

Use the EHSPI history endpoint to pull daily environmental health scores across multiple cities and sensitivities for a defined time window. Correlate with clinical outcomes data. The published weight vectors allow full methodological transparency in any resulting publication.

GET /v1/ehspi/history GET /v1/trends Published weights
Contact the research team