SlimSlim/Health

Get health status

  • Sandbox: available
  • Staging: available
  • Production: unknown
GET
/v1/slim/health

Returns the health of the Slim API and the systems it depends on. Use it for uptime checks and status screens.

Auth: none.

Behaviour

  • status is healthy when both the FHIR store and Redis are up, degraded when one is down, and unhealthy when both are down. The route still answers 200 in every case, so read status, not the HTTP code.
  • externalSystems.fhirStore and externalSystems.redis hold each system's own status and, when available, its version, memory and connection figures. responseTimeMs is the time the FHIR store took to answer its health check.
  • cache holds hit, miss and error counts of the application cache since the process started.
  • ovok, system and the FHIR store serverMetrics come from the monitoring system, from the last 5 minutes. They are left out when monitoring is not configured or does not answer.
  • uptimeSeconds is the time since this process started. version is null when the deployment does not set one.

Example

curl -X GET 'https://api.sandbox.ovok.com/v1/slim/health'

Response Body

Health of the Slim API and the systems it depends on.

application/json
  1. response
status*string
Value in"healthy""degraded""unhealthy"
environment*string
version*string

Deployed version, or null when the deployment sets none.

uptimeSeconds*number

Seconds since this process started.

timestamp*string
Formatdate-time
endpoints*
externalSystems*
cache?
ovok?
system?
observability*
Example Request
curl -X GET 'https://api.sandbox.ovok.com/v1/slim/health'
Example Response
{  "status": "healthy",  "environment": "string",  "version": "string",  "uptimeSeconds": 0,  "timestamp": "2019-08-24T14:15:22Z",  "endpoints": {    "api": "string",    "fhir": "string"  },  "externalSystems": {    "fhirStore": {      "status": "up",      "version": "string",      "postgres": true,      "redis": true,      "platform": "string",      "runtime": "string",      "responseTimeMs": 0,      "serverMetrics": {        "db": {          "idleConnections": 0,          "queriesAwaitingClient": 0,          "healthcheckRttSeconds": 0        },        "memory": {          "usedHeapBytes": 0,          "oldSpaceBytes": 0,          "newSpaceBytes": 0        },        "queues": {          "batchWaiting": 0,          "batchDelayed": 0,          "cronWaiting": 0,          "cronDelayed": 0,          "subscriptionWaiting": 0,          "subscriptionDelayed": 0        },        "fhirOps": {          "readCount": 0,          "searchCount": 0,          "createCount": 0,          "updateCount": 0,          "deleteCount": 0,          "patchCount": 0        },        "server": {          "indexingDurationMsMax": 0,          "validationDurationMsMax": 0        }      }    },    "redis": {      "status": "up",      "uptimeSeconds": 0,      "connectedClients": 0,      "usedMemoryBytes": 0,      "usedMemoryHuman": "string",      "peakMemoryBytes": 0,      "peakMemoryHuman": "string",      "opsPerSecond": 0,      "hitRate": 0,      "evictedKeys": 0,      "blockedClients": 0    }  },  "cache": {    "hits": 0,    "misses": 0,    "errors": 0,    "hitRate": 0  },  "ovok": {    "cpuUsage": 0,    "memoryUsageBytes": 0,    "eventLoopLagMs": 0  },  "system": {    "cpuUtilization": 0,    "loadAverage1m": 0,    "loadAverage5m": 0,    "loadAverage15m": 0,    "memoryUsageBytes": 0  },  "observability": {    "signoz": "string"  }}

Create night report PDF POST

Creates a night report PDF for one resident and stores it. Optionally emails the PDF. Use it for the report download and email feature on the dashboard. **Auth:** bearer token. The caller must be a practitioner, an admin or a System Owner, and needs `search` and `read` on `Patient`, `Device` and `Observation`. **Scope:** the caller's project (from the token). The resident is read with your token, so Medplum's access policy limits which residents you can export. ## Behaviour - `code` must be `TRENDS_PDF_EXPORT`. Any other value is rejected with `400`. - The report layout comes from the export template content for `code` and `language`. A template in your project wins over one in its parent project. The route returns `400` when no template exists. - The report period is `(period.start, period.end]` in the project's time zone: for a range of more than one day the first day is left out, because its night belongs to the day before. A single-day range reports that day. A night counts for the day its sleep ends. - The report covers sleep statistics, heart rate and respiratory rate for each night. It holds only what ends inside one of the resident's use periods of its device, as `GET /v1/slim/sleep/statistics` does: the sleep table's recordings, and the readings behind the heart and respiratory rate rows and charts. A reading with no end time is then left out. So a previous resident's night that ended before the device was handed over, but reached Ovok after it, is not reported. A resident with no device use history has everything reported. - When a night has several sleep recordings left, the sleep table uses the one written last (latest `meta.lastUpdated`), the rule `GET /v1/slim/sleep/statistics` uses. - Once a resident has any use period, the report also leaves out what a device with no period of theirs recorded, and what a device recorded before its earliest period. A device assigned before use periods were recorded gets its first one on its next edit in Ovok, starting at the Device's last write before that edit, so what it recorded before then is not reported. Each device whose readings in a report all drop is counted in the `sleep.device_use_device_dropped` metric and logged at most once a minute. - Report times use the project's time zone. The `timeZone` field in the body is not used. - The PDF is stored as a Binary, and a `DocumentReference` links it to the resident. Both are written in one transaction, so a failed store leaves neither. The response is that `DocumentReference`. Its `content[0].attachment.url` points to the Binary. - When `mailTo` has addresses, the PDF is emailed to them as an attachment after the store succeeds. The email is sent in the language you set. With no addresses, nothing is emailed. - If the email cannot be sent, the route returns `500`, but the report has already been stored. - Every call creates a new report. Nothing is deduplicated. ## Example ```bash curl -X POST 'https://api.sandbox.ovok.com/v1/slim/export/pdf' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk' \ -H 'Content-Type: application/json' \ -d '{ "code": "TRENDS_PDF_EXPORT", "patientId": "c3499c27-2973-0a7f-807e-fb8676a92dcb", "language": "en", "period": { "start": "2026-09-21T00:00:00Z", "end": "2026-09-28T00:00:00Z" }, "mailTo": ["max.mustermann@example.com"] }' ```

Invite practitioner POST

Invites a practitioner to your project, or to one of its direct child projects, and emails them a link to set their password. **Auth:** Bearer token for a practitioner, project admin or System Owner session. The caller's access policy must grant `Practitioner:create` (a project admin who holds no access policy skips this check). **Scope:** The caller's project (from the token), or `projectId` when given. `projectId` must be the caller's project or a direct child of it. ## Behaviour - Practitioner invitations must be enabled on the target project. They are enabled unless the project turns them off. - `accessPolicyId` must name a policy of your project, its parent or a direct child, at or below your own rank. It is checked before anything is written. - An existing practitioner account with this `email` in the target project is refused: an invite never changes a member's role or admin flag (use `PUT /v1/slim/policy/{id}`). An existing practitioner account elsewhere, your own project included, is reused: only the membership and practitioner profile are new. A patient account of another project is not: it is that project's own, and the invitee gets a practitioner account of their own. - Ovok creates the membership with the access policy and the practitioner profile, then emails an invitation with a password-setup link. The link points to the app the request came from, and sets a password for 7 days after it was sent. If the email fails, the account is undone and the request answers 400. - `admin` in the body is ignored. The invitee becomes an admin member, and the project owner, only when the target project has no owner yet. - The invitee shows as `Pending` in user lists until they set a password. - Returns the new membership, the practitioner profile and `status: "Pending"`. ## Example ```bash curl -X POST 'https://api.sandbox.ovok.com/v1/slim/invite/practitioner' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NjcyNjg4MDAsImV4cCI6MTc2NzI3MjQwMH0.Ql3B_ztDvctlyZ2z0vp4sl3ExXRQGkzmxdmTAqxNzZk' \ -H 'Content-Type: application/json' \ -d '{ "email": "max.mustermann@example.com", "name": "Max", "surname": "Mustermann", "accessPolicyId": "c3499c27-2973-0a7f-807e-fb8676a92dcb" }' ```