{"openapi":"3.1.0","info":{"title":"I AM GRACE Native API","version":"1.1.0","description":"GRACE's native protocol (grace.v1) — vendor-neutral REST/JSON that works without HL7 or FHIR in the middle. Inbound feeds live under /api/ingest/*; the keyed read API lives under /api/v1/*. All endpoints authenticate with a scoped Bearer API key (prefix grace_). Read endpoints return the protocol envelope { protocol, ok, data, meta }; on error { protocol, ok:false, error:{ code, message, docs } }. Mint keys at /app/integrations. Outbound state webhooks (surge.level_changed, room.rescored) are described under x-grace-state-webhooks."},"servers":[{"url":"https://iamgrace.baby"}],"security":[{"ApiKey":[]}],"x-grace-protocol":"grace.v1","x-grace-state-webhooks":{"description":"Server-emitted, HMAC-signed events fired whenever the computed verdict changes. Configure endpoints per-hospital in GRACE → Settings → Integrations. Each delivery is the grace.v1 envelope: { protocol, id, event, hospitalId, occurredAt, summary, level, priorLevel, data }. Verify X-Grace-Signature = 'sha256=' + HMAC_SHA256(secret, rawBody).","events":{"surge.level_changed":"Unit GRACE level changed (e.g. yellow → red). data: { level, priorLevel, drivingAxis, drivingAxisLabel, nurseAcuityRatio, awhonnShortfall }.","room.rescored":"A room's color changed. data: { roomId, roomLabel, color, priorColor, score, factors, nursingLevel }."}},"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"Scoped hospital API key. Format: grace_<hex>."}},"schemas":{"ClinicalSignal":{"type":"object","required":["kind","system","code"],"properties":{"kind":{"type":"string","enum":["medication","observation","lab","device"]},"system":{"type":"string","enum":["RxNorm","LOINC","SNOMED","local"]},"code":{"type":"string"},"display":{"type":"string"},"value":{"oneOf":[{"type":"string"},{"type":"number"}]},"status":{"type":"string","example":"active"},"observedAt":{"type":"string","format":"date-time"},"startedAt":{"type":"string","format":"date-time"}}},"RosterNurse":{"type":"object","properties":{"externalId":{"type":"string"},"name":{"type":"string"},"jobCode":{"type":"string","example":"RN III"},"skillLevel":{"type":"integer","enum":[0,1,2],"description":"0 novice, 1 experienced, 2 expert/charge"},"hireDate":{"type":"string","format":"date"},"assignedRoomIds":{"type":"array","items":{"type":"integer"}}}}}},"paths":{"/api/ingest/clinical":{"post":{"summary":"Ingest clinical signals (meds/observations/labs → acuity modifiers)","security":[{"ApiKey":[]}],"x-required-scope":"ingest:clinical","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["roomId","signals"],"properties":{"roomId":{"type":"integer"},"roomLabel":{"type":"string"},"signals":{"type":"array","items":{"$ref":"#/components/schemas/ClinicalSignal"}}}}}}},"responses":{"200":{"description":"Signals applied; returns activated/expired factors."}}}},"/api/ingest/roster":{"post":{"summary":"Ingest staffing roster (skill mix + tenure)","security":[{"ApiKey":[]}],"x-required-scope":"ingest:roster","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nurses"],"properties":{"asOf":{"type":"string","format":"date-time"},"nurses":{"type":"array","items":{"$ref":"#/components/schemas/RosterNurse"}}}}}}},"responses":{"200":{"description":"Roster summarized into skill mix + tenure."}}}},"/api/ingest/fhir":{"post":{"summary":"Ingest FHIR R4 (Encounter/Condition/Observation/MedicationAdministration)","security":[{"ApiKey":[]}],"x-required-scope":"ingest:fhir","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"ADT events + clinical signals applied."}}}},"/api/ingest/hl7":{"post":{"summary":"Ingest HL7 v2 ADT message","security":[{"ApiKey":[]}],"x-required-scope":"ingest:hl7","requestBody":{"required":true,"content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"responses":{"200":{"description":"ADT applied; HL7-style ACK."}}}},"/api/ingest/adt":{"post":{"summary":"Ingest a single generic ADT event","security":[{"ApiKey":[]}],"x-required-scope":"ingest:adt","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Applied."}}}},"/api/ingest/census":{"post":{"summary":"Ingest a full room census snapshot","security":[{"ApiKey":[]}],"x-required-scope":"ingest:census","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Census applied."}}}},"/api/ingest/staffing":{"post":{"summary":"Update nurses on duty + call-staff availability","security":[{"ApiKey":[]}],"x-required-scope":"ingest:staffing","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["nursesOnDuty"],"properties":{"nursesOnDuty":{"type":"integer"},"callStaffAvailable":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Staffing updated."}}}},"/api/ingest/batch":{"post":{"summary":"Bulk ADT backfill (≤500 events)","security":[{"ApiKey":[]}],"x-required-scope":"ingest:batch","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Processed."}}}},"/api/ingest/status":{"get":{"summary":"Ingest pipeline + unit-state health","security":[{"ApiKey":[]}],"x-required-scope":"read:status","responses":{"200":{"description":"Status."}}}},"/api/v1/unit-state":{"get":{"summary":"Read the full computed GRACE verdict (native protocol)","description":"Authoritative server-computed view: unit level, driving axis, per-axis breakdown, AWHONN shortfall, roster, and per-room scores. Recomputed on read, so it is correct with no dashboard open.","security":[{"ApiKey":[]}],"x-required-scope":"read:unit-state","responses":{"200":{"description":"grace.v1 envelope with the unit-state view in `data`."},"404":{"description":"No unit state recorded yet for this hospital."}}}},"/api/v1/level":{"get":{"summary":"Read the compact GRACE level + driver (native protocol)","description":"Lightweight headline verdict, cheap to poll for status pages and checks.","security":[{"ApiKey":[]}],"x-required-scope":"read:unit-state","responses":{"200":{"description":"grace.v1 envelope with { level, drivingAxis, ... } in `data`."}}}},"/api/v1/predict":{"get":{"summary":"Read the GRACE level + staffing-demand forecast (native protocol)","description":"Builds the current snapshot server-side and returns the level trajectory plus an 8-hour AWHONN staffing forecast.","security":[{"ApiKey":[]}],"x-required-scope":"read:predict","responses":{"200":{"description":"grace.v1 envelope with { current, prediction, staffingForecast } in `data`."},"422":{"description":"Insufficient history to forecast yet."}}}}}}