Overview
TB Predict scores the risk that a patient's TB treatment ends badly, and keeps the record behind every score. Other systems — a patient management system, a data warehouse, a dashboard — use it through two APIs on the same database and the same prediction pipeline, so nothing can drift between them.
FHIR server /fhir/
HL7 FHIR R4. Every clinical read and write goes through it — this website's included: patients, observations, predictions, follow-ups, alerts, geography, the audit trail, scoring and register upload.
Core API /api/
What FHIR has no resources for: signing in, user administration, and the aggregate analytics — county roll-ups, facility anomaly detection, model evaluation and findings.
Quick start
Three steps from nothing to your first patient read.
-
1
Get an account
Request access for the facility, sub-county, county or national level your integration serves. A super-administrator approves it; the API then returns exactly the patients that level covers.
-
2
Get a token
Sign in with the account's username (or email) and password. The response carries a token.
curl -X POST http://tbmldashboard.masterclass.co.ke/api/auth/login/ \ -H "Content-Type: application/json" \ -d '{"username": "your-username", "password": "your-password"}' # → { "token": "9f2c…", … } -
3
Call the FHIR server
Send the token as a Bearer token. Find a patient by TB registration number, then fetch the whole record in one call.
curl "http://tbmldashboard.masterclass.co.ke/fhir/Patient?identifier=TB123456" \ -H "Authorization: Bearer <token>" \ -H "Accept: application/fhir+json" curl "http://tbmldashboard.masterclass.co.ke/fhir/Patient/<id>/$everything" \ -H "Authorization: Bearer <token>"
Authentication & access
- Tokens.
POST /api/auth/login/returns one. Send it on every request asAuthorization: Bearer <token>(the FHIR convention) orAuthorization: Token <token>— both are accepted everywhere. - Expiry. A token stops working 12 hours after it is issued, whatever the activity. Signing in again issues a new one;
POST /api/auth/logout/revokes the current token at once. - Scope. Every clinical resource is limited to the account's access level — national, county, sub-county or facility. A record outside it answers
404, exactly like one that does not exist, so probing ids reveals nothing. - Audit. Every read of a patient's record is logged, and super-administrators can read the trail as
AuditEventresources. - Public, no token needed:
/fhir/metadata, the conformance resources,Organization,Location,Device,$validateand/api/health/. - Browsers. The server sends no CORS headers: integrations are expected to call it from a server, not from a web page on another site.
Resources
Paths are relative to http://tbmldashboard.masterclass.co.ke/fhir/. Search parameters in the notes; the CapabilityStatement lists every one formally.
| Resource | Interactions | Access | Notes |
|---|---|---|---|
Patient | read, search | Token | ?identifier=<TIBU number or national ID>, ?name=, ?organization=; _revinclude=RiskAssessment:subject. |
Observation | read, search | Token | ?patient= (required), &code=, &category= — model inputs, outcomes, lab, CD4, X-ray AI. |
RiskAssessment | read, search | Token | Our predictions (numeric ids) and TIBU's (ids tibu-N). ?patient=, ?method=, ?method:not=, ?date=, ?probability=; _sort=-date; _include=RiskAssessment:subject. |
Task | read, search, patch | Token | High-risk follow-ups. ?status=, ?business-status=, ?patient=; _include=Task:patient, Task:focus. PATCH takes JSON Patch on /status, /businessStatus and /note. |
Flag | read, search | Token | Patients whose latest prediction is at or above the alert cutoff, highest first. _include=Flag:patient, Flag:detail. |
MedicationStatement | read, search | Token | ?patient= — the TB regimen. |
Condition | read, search | Token | ?patient= — comorbidities (carries a restricted security label). |
Organization | read, search | Public | Facilities. ?name=, ?identifier=<MFL code>, ?address-state=<county>. |
Location | read, search | Public | Counties (?partof:missing=true) and sub-counties (?partof=Location/county-N). |
Device | read | Public | Model versions. |
AuditEvent | read, search | Admin | The audit trail, for super-administrators. ?date=ge…&date=le…, ?subtype=<action>, ?agent-name=, ?patient=. |
Operations
FHIR operations for what a plain read or search cannot do.
| Operation | Method | Access | What it does |
|---|---|---|---|
Patient/$predict-outcome | POST | Token | Parameters in: a Patient plus Observations. Scores with the live model, saves the assessment and raises a follow-up Task when the patient is flagged. Parameters out: the RiskAssessment and, when raised, the Task. |
Patient/{id}/$predict-outcome | POST | Token | Re-scores a known patient from their latest assessment, with optional what-if values. |
Patient/{id}/$everything | GET | Token | The whole record in one Bundle: predictions, TIBU's score, observations, regimen, comorbidities, follow-ups and alerts. |
$ingest-register | POST | Admin | Bulk upload of a DSTB register export (a base64 CSV Attachment). Idempotent by serial number; dryRun and score flags. |
$calibration | GET | Token | Predicted against observed unfavourable-outcome rate, by model version. Small cells are suppressed. |
{Type}/$validate | POST | Public | Checks a resource against one of the published profiles and returns an OperationOutcome. |
Requesting a prediction
Post a Parameters resource carrying the patient and whatever observations are known — only age, sex and county are required. The answer is the prediction as a RiskAssessment, and the follow-up Task when the patient is flagged.
POST /fhir/Patient/$predict-outcome
Authorization: Bearer <token>
Content-Type: application/fhir+json
{
"resourceType": "Parameters",
"parameter": [
{ "name": "patient",
"resource": { "resourceType": "Patient", … } },
{ "name": "observation",
"resource": { "resourceType": "Observation", … } }
]
}
HTTP/1.1 200 OK
Content-Type: application/fhir+json
{
"resourceType": "Parameters",
"parameter": [
{ "name": "riskAssessment",
"resource": { "resourceType": "RiskAssessment", … } },
{ "name": "task",
"resource": { "resourceType": "Task", … } }
]
}
Searching & paging
- Searches return
searchsetBundles withtotal, afullUrlandsearch.modeon every entry, andself/next/previouslinks. - Page with
_count— 50 by default, up to 1,000 — and follow thenextlink rather than building page URLs yourself. _summary=countreturns the total only;_elementsreturns a marked subset of each resource._includeand_revincludeare honoured where the resource declares them (see Resources), and_sortonRiskAssessment(date),Task(authored-on) andAuditEvent(date).
Errors
The FHIR server answers every error with an OperationOutcome saying what went wrong. The core API answers {"error": "…"} — or {"detail": "…"} for sign-in failures — with a standard status code.
- 400The request is malformed, or a search parameter is not supported.
- 401No token, or an expired one. Carries a WWW-Authenticate: Bearer challenge.
- 403Signed in, but the action needs a higher role.
- 404No such resource — or one outside your access level; the two look the same.
- 405 / 406 / 415Wrong method, an Accept the server cannot satisfy, or a body in an unsupported format.
- 422The body is well-formed FHIR but fails validation (for example, a missing required input).
- 503The prediction model is not loaded.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
{
"resourceType": "OperationOutcome",
"issue": [{
"severity": "error",
"code": "login",
"diagnostics": "…"
}]
}
Conformance
GET /fhir/metadatareturns the CapabilityStatement — the machine-readable list of every resource, search parameter and operation this server supports.- Every profile, code system and value set it uses is published on the server too, under
StructureDefinition,CodeSystem,ValueSet,OperationDefinitionandSearchParameter. - Output is checked with the official HL7 FHIR validator in the backend's test suite, and every reference a resource carries resolves on this server.
- Check your own resources before sending them with
POST /fhir/{Type}/$validate.
Core API
Paths are relative to http://tbmldashboard.masterclass.co.ke/api/.
| Method | Path | Access | What it does |
|---|---|---|---|
| POST | auth/login/ | Public | Sign in; returns a token. |
| POST | auth/logout/ | Token | Revoke the current token. |
| GET | auth/me/ | Token | The signed-in user's profile, role and access level. |
| POST | auth/register/ | Public | Request an account (it waits for approval). |
| POST | auth/password-reset/ | Public | Email a password-reset link. |
| GET/POST | auth/… | Admin | Approvals, suspensions, roles, access levels and settings. |
| GET | health/ | Public | Liveness and model-load status. |
| GET | model/info/ | Public | Which champion and base models are loaded. |
| GET | analytics/findings/ | Token | The sensitivity analysis and recommendations behind the Findings page. |
| GET | analytics/county-risk/ | Token | Aggregated risk by county. |
| GET | analytics/alerts/ | Token | Facility case-count anomalies (CUSUM) and the alert cutoff. |
| GET | analytics/model-performance/ | Public | Training-pipeline metrics for the candidate models. |
| GET | audit/summary/ | Admin | Audit counts by action, day and user. |
The interactive API explorer
Every core API endpoint with its request and response schemas, and a Try it out button that sends real requests with your session. Because those requests act on live data, the explorer is open to administrators only.