reference/api.md

8. API Specification & Integration

8.1 Conventions

  • Base URL https://api.travi ai agent.health/v1; JSON only; Authorization: Bearer <jwt>; TLS 1.2+.
  • Errors: RFC 9457 problem+json (type, title, status, detail, trace_id); no PHI in error bodies.
  • All mutating POSTs accept Idempotency-Key header (UUID); server stores response hash 48 h and replays on retry.
  • Pagination: cursor (?cursor=&limit≤100); list responses {items, next_cursor}.
  • Rate limits (WAF+Redis): activation 10/min/IP; patient APIs 60/min/session; clinician brief open 30/min/grant; 429 with Retry-After.
  • ETag/If-Match on GET /today and task PATCH bound to episode.version, stale writes get 409 with refresh directive.

A lightweight integration specification covering the FHIR R4 endpoints Travi consumes and exposes, authentication flow, webhook contracts, and a self-assessment checklist for hospital IT teams evaluating integration complexity.

8.2 Authentication

SMART on FHIR 2.0

Travi registers as a SMART on FHIR app in the hospital's EHR App Gallery. OAuth 2.0 authorization code flow with PKCE. Scopes requested: patient/*.read, user/Task.write, user/Communication.write, user/ClinicalImpression.write.

JWT Bearer Tokens

All Travi API endpoints require a signed JWT bearer token. Tokens are scoped per hospital, expire in 1 hour, and are rotated automatically. Hospital IT teams receive a client ID and client secret during onboarding, no API keys are shared with clinical staff.

Mutual TLS (mTLS)

For hospitals that require it, Travi supports mTLS on the FHIR ingest endpoint. The hospital provides a client certificate during onboarding; Travi pins the certificate and rejects connections from any other source.

8.3 Inbound: FHIR Resources Travi Reads

FHIR Resource Trigger Key Fields Used Required
Encounter status = finished, class = IMP (inpatient) period.end, subject, hospitalization.dischargeDisposition YES
Patient Pulled on discharge event name, telecom (phone), birthDate, address, language YES
MedicationRequest status = active, linked to Encounter medication.code, dosageInstruction, dispenseRequest.numberOfRepeatsAllowed YES
DocumentReference type = discharge summary (LOINC 18842-5) content.attachment (base64 or URL), context.encounter YES
Appointment status = booked, linked to Patient start, end, participant, serviceType OPTIONAL
Observation category = vital-signs or laboratory, last 30 days code (LOINC), valueQuantity, effectiveDateTime OPTIONAL
Condition clinicalStatus = active, linked to Patient code (ICD-10), severity, onsetDateTime OPTIONAL

8.4 Outbound: FHIR Resources Travi Writes

FHIR Resource Purpose Trigger Frequency
Task Care plan task status (completed, in-progress, failed) Patient SMS response or daily batch Daily or on event
Communication Log of all patient-Travi SMS interactions Each SMS sent or received Real-time
ClinicalImpression AI-generated risk assessment with score and rationale Risk score threshold crossed or daily Daily + on escalation
Flag High-risk patient alert visible in EHR patient banner Escalation engine fires On escalation only

8.5 Webhook Contract

Travi exposes a single inbound webhook endpoint for EHR systems that push rather than allow polling:

POST https://api.travi.ai/v1/fhir/webhook
Authorization: Bearer <hospital_jwt>
Content-Type: application/fhir+json
X-Travi-Signature: sha256=<hmac_signature>

{
  "resourceType": "Bundle",
  "type": "transaction",
  "entry": [
    { "resource": { "resourceType": "Encounter", ... } },
    { "resource": { "resourceType": "Patient", ... } }
  ]
}

All webhook payloads are HMAC-SHA256 signed using the hospital's shared secret. Travi validates the signature before processing. Idempotency key: Encounter.id, duplicate discharge events for the same encounter are deduplicated automatically. Response: 202 Accepted within 200ms; processing is async.

8.6 Analytics API (Hospital Read-Only)

Endpoint Returns Auth
GET /v1/analytics/readmissions 30-day readmission rate by cohort, DRG, and month Hospital admin JWT
GET /v1/analytics/adherence Medication fill rate, appointment attendance, task completion by cohort Hospital admin JWT
GET /v1/analytics/hrrp Projected HRRP penalty reduction and estimated dollar savings Hospital admin JWT
GET /v1/analytics/tcm-billing TCM-eligible encounters, billed vs. unbilled, CPT code breakdown Hospital admin JWT
GET /v1/patients/{id}/timeline Full 30-day task and interaction timeline for a single patient Care coordinator JWT (own cohort only)

8.7 Endpoint Catalog

Patient & Caregiver surface

Verb Path Purpose / Notes
POST /patient/activate/start Body: activation token. Returns verification challenge spec. Never discloses episode existence on failure (ENR-005).
POST /patient/activate/verify DOB + channel proof → access+refresh tokens; consent state included; 5/24 h lockout.
POST /auth/refresh · /auth/logout Rotating refresh with reuse detection → family revocation; logout kills session + SW purge signal.
GET /today ≤3 primary actions + secondary list; server-ordered (PAT-001); ETag=episode.version.
PATCH /tasks/{id}/response Body: done|not_yet|cannot_do|not_sure (+barrier_code). Drives §7.1 transitions (PAT-005).
GET /medications Plan items + latest status per dimension; verified flag explicit (MED-006).
POST /medications/{id}/status Patient-report status event; server assigns evidence_class=patient_report.
GET/POST /appointments · /appointments/assist List reqs+appts; submit assisted-scheduling request without re-entering demographics (APT-004).
GET /plan · /visit-prep/{apptId} · /handoff 30-day timeline w/ provenance labels; visit prep questions; day-30 summary.
GET/POST /consents · /caregivers · DELETE /caregivers/{id} Consent views/updates; caregiver invite (own token flow) & instant revoke (CGV-004).
GET /emergency-card Minimal offline payload (contact, 911 text, med names+sig); served with SW cache headers (ADR-012).

Clinician surface

Verb Path Purpose / Notes
POST /clinician/access/start · /verify Magic-link token → email OTP (6-digit, 10 min) → grant JWT bound to device fingerprint (§9.3).
GET /clinician/brief/{grantId} Runs staleness check (§14.4); returns snapshot or 202 {regenerating} → poll ≤5 s.
GET /clinician/brief/{id}/source/{factId} Source viewer: span text + hierarchy decision (DPC-008).
POST /clinician/confirmations Confirm/reject pending material items; requires step-up OTP ≤5 min old (VIS-007).
POST /clinician/post-visit Upload note/AVS (S3 presigned) or structured summary → reprocess loop (VIS-005).

Admin, integration & webhooks

Verb Path Purpose / Notes
CRUD /admin/cohorts · /templates · /config Versioned publish (draft→review→published); never mutates active episodes (§2.2).
POST /admin/kill-switches Six scopes (§16.4); takes effect ≤10 s; reason mandatory; audited.
GET /admin/reports/execution · /outcomes ADM-004 categories; ADM-007 with completeness/coverage footers (ADR-016).
POST /admin/overrides/eligibility ENR-002 override with reason; duplicate-episode guard.
POST /integration/adt HL7v2 over MLLP→HTTPS bridge from interface engine (VPN); HMAC-signed; idempotent on MSH-10.
POST /webhooks/twilio · /webhooks/ses Delivery status; signature-validated; drives channel ladder.

8.8 Representative Payload

PATCH /v1/tasks/9f2e.../response GET /v1/today (excerpt)
{ {
 "response": "cannot_do", "episode_version": 41,
 "barrier_code": "cost" "primary": [{
} "task_id": "9f2e...",
→ 200 "category": "medication",
{ "priority": "critical",
 "task": {"id":"9f2e...", "title": "Pick up spironolactone",
 "state":"blocked", "due_at": "2026-07-15",
 "barrier_code":"cost"}, "provenance": {"label":"From your signed
 "next": {"type":"barrier_flow", discharge summary","level":1},
 "flow":"med_cost_assist"} "actions": ["done","not_yet",
} "cannot_do","not_sure"]}]
 }

8.9 Hospital IT Self-Assessment Checklist

Use this checklist to estimate integration complexity before the first call with Travi's integration team. All "YES" answers indicate a standard 6–8 week integration. Each "NO" adds 1–3 weeks.

☐
FHIR R4 endpoint available
EHR exposes a FHIR R4 API (Epic FHIR, Oracle FHIR, or equivalent)
☐
SMART on FHIR app registration supported
IT team can register a third-party SMART app in the EHR app gallery
☐
ADT events accessible via FHIR Subscription or webhook
Discharge events can be pushed or polled in near-real-time
☐
Discharge summaries in DocumentReference
Discharge summary text accessible as FHIR DocumentReference (LOINC 18842-5)
☐
Task resource write-back permitted
Third-party apps can write Task, Communication, and ClinicalImpression resources back to the EHR
☐
Patient phone numbers in telecom field
Patient.telecom contains a mobile phone number for SMS delivery
☐
BAA can be executed with Travi
Legal and compliance team can sign a Business Associate Agreement before go-live
☐
Sandbox / test environment available
EHR has a non-production sandbox with synthetic patient data for integration testing
Integration Support

Travi provides a dedicated integration engineer for every pilot and contract customer. The integration engineer handles SMART app registration, data mapping, UAT coordination, and go-live monitoring. A sandbox environment with synthetic patient data is available for testing before any production data is accessed. Full integration documentation is available under NDA.

See also: FHIR R4 Data Flow, architecture diagram showing how these resources move through the pipeline, and Security Architecture, for PHI handling and compliance details.