The feature was removed; the docs still described it as live. Worst of it was api-reference.md, which documented nine /api/learning endpoints and fourteen /api/admin/learning CMS endpoints — routes that answer 404 — plus POST /api/user/webdav-path, whose column was dropped by migration. Anyone reading them was reading fiction. Checked against the running system rather than assumed: no learning table exists, users.webdav_learning_path is gone, generated_image_links is gone, and no route mounts /api/learning or /api/admin/learning. Two things that look like Learning Hub and are not, so they stay: - learningRetrieval.js is live — My Resources uses it. Its settings keep the learning.* names because renaming them would orphan whatever an administrator has already set. retrieval-tuning.md now says so instead of listing the rows under two different feature names. - the moderator role is still assignable. It gated the CMS and now grants nothing; authentication.md says that rather than implying powers it does not have. moderatorMiddleware has no callers left, which is worth removing on its own. auth-admin-learning.md is now auth-admin.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2138 lines
43 KiB
Markdown
2138 lines
43 KiB
Markdown
# API Reference
|
|
|
|
Working endpoint reference for the main PedAI flows. It covers the clinical, auth, user data, and admin surfaces most commonly used by the frontend, but the source of truth is still `server.js` plus `src/routes/*.js`. Unless noted otherwise, authenticated endpoints require a valid web cookie or `Authorization: Bearer <token>` header.
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
- [Authentication](#authentication)
|
|
- [OIDC / SSO](#oidc--sso)
|
|
- [AI Generation](#ai-generation)
|
|
- [Transcription](#transcription)
|
|
- [Text-to-Speech](#text-to-speech)
|
|
- [Models](#models)
|
|
- [Encounters](#encounters)
|
|
- [Memories](#memories)
|
|
- [Audio Backups](#audio-backups)
|
|
- [Documents](#documents)
|
|
- [User Preferences](#user-preferences)
|
|
- [Phone Extensions And Pagers](#phone-extensions-and-pagers)
|
|
- [Nextcloud Integration](#nextcloud-integration)
|
|
- [Admin - Users](#admin---users)
|
|
- [Admin - Configuration](#admin---configuration)
|
|
- [Logs](#logs)
|
|
- [Milestones (Admin)](#milestones-admin)
|
|
- [Endpoint index (not detailed above)](#endpoint-index-not-detailed-above)
|
|
- [Health](#health)
|
|
- [Metrics](#metrics)
|
|
|
|
---
|
|
|
|
## Authentication
|
|
|
|
Base path: `/api/auth/`
|
|
|
|
### POST /api/auth/register
|
|
|
|
Register a new user account. The first user to register is automatically assigned the admin role. Turnstile is required only when `TURNSTILE_SECRET_KEY` is configured. If SMTP is configured, the response asks the user to verify email; without SMTP, the account is auto-verified and logged in.
|
|
|
|
- **Auth required:** No
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"name": "string",
|
|
"email": "string",
|
|
"password": "string",
|
|
"turnstileToken": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"needsVerification": true,
|
|
"message": "Check your email for verification link."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/auth/verify-email
|
|
|
|
Verify a user's email address via the link sent during registration.
|
|
|
|
- **Auth required:** No
|
|
- **Query parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|--------------------------------------|
|
|
| `token` | string | Email verification token from the link |
|
|
- **Response:** HTML status page for success or expired/invalid token.
|
|
|
|
---
|
|
|
|
### POST /api/auth/resend-verification
|
|
|
|
Resend the email verification link.
|
|
|
|
- **Auth required:** No
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"email": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Verification email sent."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/auth/login
|
|
|
|
Authenticate a user. Supports optional TOTP two-factor authentication. On success, sets an HTTP-only JWT cookie and returns user data.
|
|
|
|
- **Auth required:** No
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"email": "string",
|
|
"password": "string",
|
|
"totpCode": "string (optional, required if 2FA is enabled)"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"token": "jwt-string",
|
|
"sessionId": "string",
|
|
"user": {
|
|
"id": "number",
|
|
"name": "string",
|
|
"email": "string",
|
|
"role": "admin | moderator | user",
|
|
"totp_enabled": "boolean",
|
|
"email_verified": "boolean"
|
|
}
|
|
}
|
|
```
|
|
If 2FA is enabled but `totpCode` is not provided:
|
|
```json
|
|
{
|
|
"requires2FA": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/auth/setup-2fa
|
|
|
|
Generate a TOTP secret and QR code for setting up two-factor authentication.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:** None
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"secret": "string",
|
|
"qrCode": "string (data URI)"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/auth/verify-2fa
|
|
|
|
Verify a TOTP code and enable two-factor authentication for the user.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"code": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"backupCodes": ["string"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/auth/disable-2fa
|
|
|
|
Disable two-factor authentication. Requires password confirmation.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"password": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/auth/forgot-password
|
|
|
|
Initiate password reset. Sends a reset link to the user's email.
|
|
|
|
- **Auth required:** No
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"email": "string",
|
|
"turnstileToken": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "If account exists, reset email sent"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/auth/reset-password
|
|
|
|
Reset the user's password using a valid reset token.
|
|
|
|
- **Auth required:** No
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"token": "string",
|
|
"newPassword": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"passwordWarning": "string (optional)"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/auth/logout
|
|
|
|
Log out the current user by deleting the current session row when a token is present and clearing the auth cookie.
|
|
|
|
- **Auth required:** No
|
|
- **Request body:** None
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/auth/me
|
|
|
|
Retrieve the currently authenticated user's profile.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"user": {
|
|
"id": "number",
|
|
"name": "string",
|
|
"email": "string",
|
|
"role": "admin | moderator | user",
|
|
"totp_enabled": "boolean",
|
|
"email_verified": "boolean",
|
|
"canLocalAuth": "boolean"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/auth/registration-status
|
|
|
|
Check whether new user registration is enabled on this instance.
|
|
|
|
- **Auth required:** No
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"registrationEnabled": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## OIDC / SSO
|
|
|
|
Base path: `/api/auth/`
|
|
|
|
### GET /api/auth/oidc-status
|
|
|
|
Check whether OIDC single sign-on is configured and enabled.
|
|
|
|
- **Auth required:** No
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"oidcEnabled": true,
|
|
"disableLocalAuth": false,
|
|
"buttonLabel": "Sign in with SSO"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/auth/oidc
|
|
|
|
Initiates the OIDC login flow. Redirects the user to the configured identity provider.
|
|
|
|
- **Auth required:** No
|
|
- **Response:** HTTP 302 redirect to the IdP authorization endpoint.
|
|
|
|
---
|
|
|
|
### GET /api/auth/oidc/callback
|
|
|
|
Handles the callback from the identity provider after authentication. Processes the authorization code and creates/logs in the user.
|
|
|
|
- **Auth required:** No
|
|
- **Query parameters:** Standard OIDC callback parameters (`code`, `state`).
|
|
- **Response:** Redirects to the application with a session cookie set.
|
|
|
|
---
|
|
|
|
## AI Generation
|
|
|
|
All generation endpoints require authentication and stream or return AI-generated clinical text. Each accepts a `model` parameter to select the LLM.
|
|
|
|
### POST /api/generate-hpi-encounter
|
|
|
|
Generate a History of Present Illness note from a patient encounter transcript.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"transcript": "string",
|
|
"patientAge": "string",
|
|
"patientGender": "string",
|
|
"model": "string",
|
|
"setting": "string",
|
|
"physicianMemories": "string (optional)"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, generated `hpi`, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/generate-hpi-dictation
|
|
|
|
Generate an HPI note from a physician's dictated summary (same parameters as encounter).
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"transcript": "string",
|
|
"patientAge": "string",
|
|
"patientGender": "string",
|
|
"model": "string",
|
|
"setting": "string",
|
|
"physicianMemories": "string (optional)"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, generated `hpi`, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/generate-soap
|
|
|
|
Generate a SOAP note from a patient encounter transcript.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"transcript": "string",
|
|
"patientAge": "string",
|
|
"patientGender": "string",
|
|
"model": "string",
|
|
"type": "string",
|
|
"additionalInstructions": "string (optional)",
|
|
"physicianMemories": "string (optional)"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, generated `soap`, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/generate-chart-review
|
|
|
|
Generate a chart review summary from clinical notes.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"notes": "string",
|
|
"visitType": "string",
|
|
"model": "string"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, generated chart review content, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/generate-hospital-course
|
|
|
|
Generate a hospital course summary from clinical notes.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"notes": "string",
|
|
"patientAge": "string",
|
|
"patientGender": "string",
|
|
"model": "string",
|
|
"format": "string",
|
|
"physicianMemories": "string (optional)"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, generated summary, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/well-visit/shadess
|
|
|
|
Generate a SHADESS (Strengths, Home, Activities, Drugs, Emotions, Sexuality, Safety) assessment from well-visit responses.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"responses": "object",
|
|
"patientAge": "string",
|
|
"model": "string"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, generated assessment, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/sick-visit/note
|
|
|
|
Generate a sick visit note from chief complaint, transcript/dictation, ROS/PE, and diagnosis context.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"chiefComplaint": "string",
|
|
"transcript": "string (optional)",
|
|
"dictation": "string (optional)",
|
|
"patientAge": "string",
|
|
"patientGender": "string",
|
|
"model": "string",
|
|
"ros": "string (optional)",
|
|
"physicalExam": "string (optional)",
|
|
"diagnoses": "string (optional)",
|
|
"physicianMemories": "string (optional)"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, generated note, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/patient-education
|
|
|
|
Generate a parent-facing education handout from an existing clinician note. The frontend exposes this as the Handout action beside generated notes.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"noteText": "string",
|
|
"diagnosis": "string (optional)",
|
|
"medications": "string (optional)",
|
|
"patientAge": "string (optional)",
|
|
"language": "string (optional, defaults to English)",
|
|
"readingLevel": "string (optional)",
|
|
"model": "string (optional)"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"handout": "plain-text parent handout",
|
|
"model": "string"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/generate-milestone-narrative
|
|
|
|
Generate a developmental milestone narrative from milestone data.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"milestones": "object | array",
|
|
"patientAge": "string",
|
|
"patientGender": "string",
|
|
"model": "string"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, generated narrative, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/generate-milestone-summary
|
|
|
|
Generate a concise summary from a previously generated milestone narrative.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"narrative": "string",
|
|
"model": "string"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, generated summary, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/refine
|
|
|
|
Refine existing clinical text according to provided instructions.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"currentDocument": "string",
|
|
"instructions": "string",
|
|
"sourceContext": "string (optional)",
|
|
"model": "string"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, refined text, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/shorten
|
|
|
|
Shorten a block of clinical text while preserving key information.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"document": "string",
|
|
"model": "string"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, shortened text, and resolved `model`.
|
|
|
|
---
|
|
|
|
### POST /api/clarify
|
|
|
|
Improve clarity and readability of clinical text.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"document": "string",
|
|
"context": "string (optional)",
|
|
"model": "string"
|
|
}
|
|
```
|
|
- **Response:** JSON with `success`, clarified text, and resolved `model`.
|
|
|
|
---
|
|
|
|
## Transcription
|
|
|
|
### GET /api/transcribe/status
|
|
|
|
Check whether speech-to-text transcription is available and which provider is configured.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"available": true,
|
|
"provider": "litellm | none"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/transcribe
|
|
|
|
Transcribe an audio file to text. Accepts multipart form data with the audio file.
|
|
|
|
- **Auth required:** Yes
|
|
- **Content-Type:** `multipart/form-data`
|
|
- **File size limit:** 25 MB
|
|
- **Form fields:**
|
|
| Field | Type | Description |
|
|
|---------|------|--------------------|
|
|
| `audio` | file | Audio file to transcribe |
|
|
| `module` | string | Optional. What produced the recording; recorded on the backup. Defaults to `recording`. |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"text": "string",
|
|
"provider": "string",
|
|
"duration": "number (seconds)",
|
|
"backupId": "number | null"
|
|
}
|
|
```
|
|
- The audio is kept for 24 hours whether or not transcription succeeds, so this
|
|
endpoint does not need a second upload to `/api/audio-backups`. `backupId` is
|
|
`null` when the copy could not be stored — the transcription still returns,
|
|
because losing the transcript would be worse than losing the copy.
|
|
- The model is the caller's `users.stt_model`, then the `stt.model` setting,
|
|
then `LITELLM_STT_MODEL`.
|
|
|
|
---
|
|
|
|
## Text-to-Speech
|
|
|
|
### POST /api/text-to-speech
|
|
|
|
Convert text to speech. Returns an audio stream.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"text": "string",
|
|
"voice": "string (optional)"
|
|
}
|
|
```
|
|
- **Response:** Audio stream (`audio/mpeg`).
|
|
- **Response headers:**
|
|
| Header | Description |
|
|
|------------------|------------------------------------|
|
|
| `X-TTS-Provider` | The TTS provider used for synthesis |
|
|
|
|
---
|
|
|
|
## Models
|
|
|
|
### GET /api/models
|
|
|
|
List available AI models for the current instance.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"provider": "string",
|
|
"models": [
|
|
{
|
|
"id": "string",
|
|
"name": "string",
|
|
"cost": "string",
|
|
"category": "string"
|
|
}
|
|
],
|
|
"defaultModel": "string"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Encounters
|
|
|
|
### GET /api/encounters/saved
|
|
|
|
List active, unexpired saved encounters for the authenticated user.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"encounters": [
|
|
{
|
|
"id": "number",
|
|
"label": "string",
|
|
"enc_type": "string",
|
|
"status": "string",
|
|
"created_at": "string (ISO 8601)",
|
|
"updated_at": "string (ISO 8601)",
|
|
"expires_at": "string (ISO 8601)",
|
|
"transcript_preview": "string",
|
|
"note_preview": "string"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/encounters/saved/:id
|
|
|
|
Retrieve a single saved encounter with full data.
|
|
|
|
- **Auth required:** Yes
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-----------------|
|
|
| `id` | number | Encounter ID |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"encounter": {
|
|
"id": "number",
|
|
"label": "string",
|
|
"enc_type": "string",
|
|
"transcript": "string",
|
|
"generated_note": "string",
|
|
"partial_data": "stringified JSON",
|
|
"created_at": "string (ISO 8601)",
|
|
"updated_at": "string (ISO 8601)"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/encounters/saved
|
|
|
|
Create or update a saved encounter. Uses `idempotency_key` to prevent duplicates on create and `expected_version` for optimistic locking on updates.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"id": "number (optional, update existing encounter)",
|
|
"label": "string",
|
|
"enc_type": "string",
|
|
"transcript": "string",
|
|
"generated_note": "string",
|
|
"partial_data": "object (optional)",
|
|
"status": "string (optional)",
|
|
"idempotency_key": "string (optional)",
|
|
"expected_version": "number (optional, update only)"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"id": "number",
|
|
"version": "number (updates only)"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### DELETE /api/encounters/saved/:id
|
|
|
|
Delete a saved encounter.
|
|
|
|
- **Auth required:** Yes
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-----------------|
|
|
| `id` | number | Encounter ID |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Memories
|
|
|
|
Physician memories are encrypted user templates and prompt preferences. Only AI-context categories are injected into generation prompts; `custom` and legacy `correction_*` rows are excluded from `/api/memories/context`.
|
|
|
|
### GET /api/memories
|
|
|
|
List all memories for the authenticated user. Returns up to 200 entries.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"memories": [
|
|
{
|
|
"id": "number",
|
|
"category": "string",
|
|
"name": "string",
|
|
"content": "string",
|
|
"created_at": "string (ISO 8601)",
|
|
"updated_at": "string (ISO 8601)"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/memories
|
|
|
|
Create a new memory.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"category": "string",
|
|
"name": "string",
|
|
"content": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"id": "number",
|
|
"originalSize": "number",
|
|
"compressedSize": "number"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### PUT /api/memories/:id
|
|
|
|
Update an existing memory.
|
|
|
|
- **Auth required:** Yes
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-------------|
|
|
| `id` | number | Memory ID |
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"category": "string",
|
|
"name": "string",
|
|
"content": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### DELETE /api/memories/:id
|
|
|
|
Delete a memory.
|
|
|
|
- **Auth required:** Yes
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-------------|
|
|
| `id` | number | Memory ID |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/memories/context
|
|
|
|
Retrieve AI-context template/preference rows formatted for injection into AI
|
|
generation prompts. `custom` rows and legacy `correction_*` rows are excluded.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"context": "string"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Audio Backups
|
|
|
|
Encrypted 24-hour storage for recordings. Every recording made through
|
|
`/api/transcribe` is kept automatically; this group is for browser-held copies
|
|
(saved when the server could not be reached at all), and for listing,
|
|
downloading and deleting.
|
|
|
|
Payload lives in object storage when `AUDIO_BACKUPS_S3_*` is configured and in
|
|
the `audio_backups` column otherwise; metadata is always in Postgres, so these
|
|
endpoints behave identically either way. See `docs/speech.md`.
|
|
|
|
### POST /api/audio-backups
|
|
|
|
Upload an audio backup. The file is gzip-compressed and encrypted on the server.
|
|
|
|
- **Auth required:** Yes
|
|
- **Content-Type:** `multipart/form-data`
|
|
- **Form fields:**
|
|
| Field | Type | Description |
|
|
|---------|------|------------------------|
|
|
| `audio` | file | Audio file to back up |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"id": "number"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/audio-backups
|
|
|
|
List unexpired audio backups for the authenticated user.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"backups": [
|
|
{
|
|
"id": "number",
|
|
"module": "string",
|
|
"mime_type": "string",
|
|
"size_bytes": "number",
|
|
"compressed_bytes": "number",
|
|
"created_at": "string (ISO 8601)",
|
|
"expires_at": "string (ISO 8601)"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/audio-backups/:id/audio
|
|
|
|
Download a decompressed audio backup.
|
|
|
|
- **Auth required:** Yes
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-------------------|
|
|
| `id` | number | Audio backup ID |
|
|
- **Response:** Binary audio stream with appropriate content-type header.
|
|
|
|
---
|
|
|
|
### DELETE /api/audio-backups/:id
|
|
|
|
Delete an audio backup.
|
|
|
|
- **Auth required:** Yes
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-------------------|
|
|
| `id` | number | Audio backup ID |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Documents
|
|
|
|
S3-backed document storage for clinical files.
|
|
|
|
### GET /api/documents
|
|
|
|
List all documents for the authenticated user.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"s3_configured": true,
|
|
"documents": [
|
|
{
|
|
"id": "number",
|
|
"filename": "string",
|
|
"mime_type": "string",
|
|
"size_bytes": "number",
|
|
"description": "string",
|
|
"created_at": "string (ISO 8601)"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/documents/upload
|
|
|
|
Upload a document to S3 storage.
|
|
|
|
- **Auth required:** Yes
|
|
- **Content-Type:** `multipart/form-data`
|
|
- **File size limit:** 10 MB
|
|
- **Allowed types:** PDF, images (JPEG, PNG, GIF), Word documents (.doc, .docx), plain text (.txt), CSV (.csv)
|
|
- **Form fields:**
|
|
| Field | Type | Description |
|
|
|--------|------|---------------------|
|
|
| `file` | file | Document to upload |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"id": "number",
|
|
"filename": "string"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/documents/:id/download
|
|
|
|
Download a document.
|
|
|
|
- **Auth required:** Yes
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|---------------|
|
|
| `id` | number | Document ID |
|
|
- **Response:** JSON containing a short-lived pre-signed download URL.
|
|
```json
|
|
{
|
|
"success": true,
|
|
"url": "string"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### DELETE /api/documents/:id
|
|
|
|
Delete a document from S3 storage.
|
|
|
|
- **Auth required:** Yes
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|---------------|
|
|
| `id` | number | Document ID |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## User Preferences
|
|
|
|
### GET /api/user/preferences
|
|
|
|
Get the authenticated user's preferences.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"stt_model": "string",
|
|
"tts_voice": "string"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/user/preferences
|
|
|
|
Save user preferences.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"stt_model": "string",
|
|
"tts_voice": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/user/preferences/options
|
|
|
|
List available STT models and TTS voices that the user can choose from.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"sttModels": [
|
|
{ "value": "string", "label": "string" }
|
|
],
|
|
"ttsVoices": [
|
|
{ "value": "string", "label": "string" }
|
|
],
|
|
"sttProvider": "string",
|
|
"ttsProvider": "string"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Phone Extensions And Pagers
|
|
|
|
Base path: `/api/extensions`. All endpoints require authentication and operate on the current user's personal directory.
|
|
|
|
Portable import/export fields are `location`, `name`, `number`, `type`, and `notes`. Exports intentionally omit database IDs and user IDs. `type` is either `extension` or `pager`.
|
|
|
|
### GET /api/extensions
|
|
|
|
List active or trashed phone directory entries.
|
|
|
|
- **Auth required:** Yes
|
|
- **Query parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `trash` | string | `1` or `true` returns trashed entries instead of active entries. |
|
|
| `q` | string | Case-insensitive search over location, name, number, and notes. |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"items": [
|
|
{
|
|
"id": 1,
|
|
"location": "ED",
|
|
"name": "Charge Nurse",
|
|
"number": "1234",
|
|
"type": "extension",
|
|
"notes": "Nights",
|
|
"trashed_at": null,
|
|
"created_at": "2026-05-08T00:00:00.000Z",
|
|
"updated_at": "2026-05-08T00:00:00.000Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/extensions
|
|
|
|
Create a phone extension or pager entry.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"location": "ED",
|
|
"name": "Charge Nurse",
|
|
"number": "1234",
|
|
"type": "extension",
|
|
"notes": "Optional note"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"id": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### PUT /api/extensions/:id
|
|
|
|
Update an existing entry owned by the current user.
|
|
|
|
- **Auth required:** Yes
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `id` | number | Entry ID. |
|
|
- **Request body:** Same fields as `POST /api/extensions`.
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### DELETE /api/extensions/:id
|
|
|
|
Move an active entry to trash. This is a soft delete.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/extensions/:id/restore
|
|
|
|
Restore a trashed entry.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### DELETE /api/extensions/:id/purge
|
|
|
|
Permanently delete a trashed entry.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/extensions/export
|
|
|
|
Export active entries as `pedscribe-extensions.zip`. The ZIP contains `pedscribe-extensions.json`.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response headers:**
|
|
| Header | Description |
|
|
|--------|-------------|
|
|
| `Content-Type` | `application/zip` |
|
|
| `Content-Disposition` | Attachment filename. |
|
|
| `X-Export-Count` | Number of exported active entries. |
|
|
- **JSON file shape inside ZIP:**
|
|
```json
|
|
{
|
|
"format": "pedscribe-phone-directory",
|
|
"version": 1,
|
|
"exported_at": "2026-05-08T00:00:00.000Z",
|
|
"items": [
|
|
{
|
|
"location": "ED",
|
|
"name": "Charge Nurse",
|
|
"number": "1234",
|
|
"type": "extension",
|
|
"notes": "Optional note"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/extensions/import
|
|
|
|
Import entries from a JSON request body. Exact active duplicates are skipped. Exact trashed matches can be restored when requested. Possible duplicates are identified by loose matching (`location + number` or `number + type`) and skipped unless explicitly imported.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:** Export payload object, an array of entry objects, or an object with `items` and `options`.
|
|
```json
|
|
{
|
|
"items": [
|
|
{
|
|
"location": "ED",
|
|
"name": "Charge Nurse",
|
|
"number": "1234",
|
|
"type": "extension",
|
|
"notes": "Optional note"
|
|
}
|
|
],
|
|
"options": {
|
|
"restoreTrashed": true,
|
|
"importPossibleDuplicates": false
|
|
}
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"imported": 2,
|
|
"restored": 1,
|
|
"skipped": 1,
|
|
"possibleSkipped": 1,
|
|
"total": 3
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/extensions/import/preview
|
|
|
|
Preview a JSON import before committing it. The preview categorizes entries as new, exact active duplicates, exact trashed matches, or possible duplicates.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:** Same JSON shapes accepted by `POST /api/extensions/import`.
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"preview": {
|
|
"summary": {
|
|
"total": 3,
|
|
"new": 1,
|
|
"exactActive": 1,
|
|
"exactTrashed": 0,
|
|
"possible": 1
|
|
},
|
|
"entries": []
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/extensions/import-file
|
|
|
|
Import entries from a multipart file upload. Accepts a PedScribe JSON export or a ZIP export containing JSON. Form fields `restoreTrashed=true` and `importPossibleDuplicates=true` control the same duplicate handling options as JSON import.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:** `multipart/form-data` with field `file`.
|
|
- **Limits:** Maximum upload size is 1 MB. At most 1000 valid entries are processed.
|
|
- **Response:** Same as `POST /api/extensions/import`.
|
|
|
|
---
|
|
|
|
### POST /api/extensions/import-file/preview
|
|
|
|
Preview a multipart JSON or ZIP import before committing it.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:** `multipart/form-data` with field `file`.
|
|
- **Response:** Same preview shape as `POST /api/extensions/import/preview`.
|
|
|
|
---
|
|
|
|
## Nextcloud Integration
|
|
|
|
### POST /api/nextcloud/connect
|
|
|
|
Connect the user's account to a Nextcloud instance via WebDAV.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"url": "string",
|
|
"username": "string",
|
|
"password": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Connected to Nextcloud."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/nextcloud/export
|
|
|
|
Export text content to the connected Nextcloud instance.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"text": "string",
|
|
"title": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"path": "string"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/nextcloud/disconnect
|
|
|
|
Disconnect the user's Nextcloud integration.
|
|
|
|
- **Auth required:** Yes
|
|
- **Request body:** None
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Disconnected from Nextcloud."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Admin - Users
|
|
|
|
Requires admin role.
|
|
|
|
### GET /api/admin/users
|
|
|
|
List all registered users.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"users": [
|
|
{
|
|
"id": "number",
|
|
"name": "string",
|
|
"email": "string",
|
|
"role": "string",
|
|
"email_verified": "boolean",
|
|
"totp_enabled": "boolean",
|
|
"disabled": "boolean",
|
|
"created_at": "string (ISO 8601)"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/admin/users/:id
|
|
|
|
Get detailed information and usage statistics for a specific user.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-------------|
|
|
| `id` | number | User ID |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"user": {
|
|
"id": "number",
|
|
"name": "string",
|
|
"email": "string",
|
|
"role": "string",
|
|
"email_verified": "boolean",
|
|
"totp_enabled": "boolean",
|
|
"disabled": "boolean",
|
|
"api_calls": "number",
|
|
"last_login": "string (ISO 8601) | null"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/admin/users/:id/verify
|
|
|
|
Manually verify a user's email address (bypass email verification).
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-------------|
|
|
| `id` | number | User ID |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/admin/users/:id/disable
|
|
|
|
Disable a user account, preventing login.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-------------|
|
|
| `id` | number | User ID |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/admin/users/:id/enable
|
|
|
|
Re-enable a previously disabled user account.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|-------------|
|
|
| `id` | number | User ID |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Admin - Configuration
|
|
|
|
Requires admin role unless noted otherwise.
|
|
|
|
### GET /api/admin/config/announcement
|
|
|
|
Get the current announcement banner. Any authenticated user can read this endpoint.
|
|
|
|
- **Auth required:** Yes
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"enabled": "boolean",
|
|
"text": "string",
|
|
"type": "info | warning | error | success"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/admin/config
|
|
|
|
Get all application configuration settings.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:** Object containing all configuration key-value pairs.
|
|
|
|
---
|
|
|
|
### PUT /api/admin/config/:key
|
|
|
|
Update one application configuration setting. The key must match an allowed prefix: `announcement.`, `feature.`, `email.`, `prompt.`, `registration_enabled`, `registration_invite_only`, `site.`, `smtp.`, `models.`, `tts.`, `stt.`, `clinical_assistant.`, or `my_resources.`. Anything else is rejected with 400.
|
|
|
|
Some keys are refused here even when allowed: `models.*` must go through the validated model endpoints, `feature.*` values must be `true` or `false`, and any key under lockdown returns 403.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"value": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/admin/config/test-email
|
|
|
|
Send a test email to verify SMTP configuration.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"to": "string (email address)"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Test email sent."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/admin/config/prompts
|
|
|
|
Get all AI prompt templates, including any admin overrides.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:** Object mapping prompt keys to their current values.
|
|
|
|
---
|
|
|
|
### POST /api/admin/config/prompts/:key/reset
|
|
|
|
Reset a specific AI prompt template back to its default value.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Path parameters:**
|
|
| Parameter | Type | Description |
|
|
|-----------|--------|---------------------|
|
|
| `key` | string | Prompt template key |
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/admin/config/reset-defaults
|
|
|
|
Reset all configuration settings to their default values.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/admin/config/smtp/status
|
|
|
|
Check the current SMTP configuration status.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"configured": "boolean",
|
|
"host": "string",
|
|
"port": "string",
|
|
"user": "string",
|
|
"from": "string",
|
|
"source": "env | database | none"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### PUT /api/admin/config/smtp
|
|
|
|
Update SMTP email configuration.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"host": "string",
|
|
"port": "number",
|
|
"user": "string",
|
|
"pass": "string",
|
|
"from": "string",
|
|
"secure": "boolean"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/admin/settings/registration
|
|
|
|
Update registration settings (enable/disable new registrations).
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"enabled": "boolean"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/auth/oidc/config
|
|
|
|
Get the current OIDC/SSO configuration.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"config": {
|
|
"oidc.enabled": "string",
|
|
"oidc.issuer": "string",
|
|
"oidc.client_id": "string",
|
|
"oidc.client_secret": "masked string",
|
|
"oidc.disable_local_auth": "string",
|
|
"oidc.button_label": "string"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### PUT /api/auth/oidc/config
|
|
|
|
Update the OIDC/SSO configuration.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"oidc.enabled": "string",
|
|
"oidc.issuer": "string",
|
|
"oidc.client_id": "string",
|
|
"oidc.client_secret": "string",
|
|
"oidc.disable_local_auth": "string",
|
|
"oidc.button_label": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/admin/config/models
|
|
|
|
List all AI models with their enabled/disabled status.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:**
|
|
```json
|
|
[
|
|
{
|
|
"id": "string",
|
|
"name": "string",
|
|
"enabled": "boolean",
|
|
"isDefault": "boolean",
|
|
"category": "string"
|
|
}
|
|
]
|
|
```
|
|
|
|
---
|
|
|
|
### PUT /api/admin/config/models/toggle
|
|
|
|
Enable or disable a specific AI model.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"modelId": "string",
|
|
"enabled": "boolean"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### PUT /api/admin/config/models/default
|
|
|
|
Set the default AI model for all users.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"modelId": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### POST /api/admin/config/models/custom
|
|
|
|
Add a custom AI model definition.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Request body:**
|
|
```json
|
|
{
|
|
"id": "string",
|
|
"name": "string",
|
|
"category": "string"
|
|
}
|
|
```
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/admin/config/models/discover
|
|
|
|
Discover available models from the configured AI provider.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"models": [
|
|
{
|
|
"id": "string",
|
|
"name": "string"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Logs
|
|
|
|
Requires admin role.
|
|
|
|
### GET /api/logs/usage
|
|
|
|
Get a 30-day usage summary broken down by model and endpoint.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"byModel": [
|
|
{
|
|
"model": "string",
|
|
"count": "number",
|
|
"tokens": "number"
|
|
}
|
|
],
|
|
"byEndpoint": [
|
|
{
|
|
"endpoint": "string",
|
|
"count": "number"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### GET /api/logs/audit
|
|
|
|
Get the audit log of user actions (login, settings changes, etc.).
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:** Array of audit log entries with timestamps, user IDs, and action descriptions.
|
|
|
|
---
|
|
|
|
### GET /api/logs/api
|
|
|
|
Get API call metrics (request counts, latency, error rates).
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:** Array of API metric entries.
|
|
|
|
---
|
|
|
|
### GET /api/logs/access
|
|
|
|
Get user access history (login times, IP addresses).
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:** Array of access log entries.
|
|
|
|
---
|
|
|
|
## Milestones (Admin)
|
|
|
|
Developmental milestones management. Requires admin role.
|
|
|
|
### GET /api/admin/milestones
|
|
|
|
List all developmental milestones in the database.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Response:** Array of milestone objects organized by age group and domain.
|
|
|
|
---
|
|
|
|
### POST /api/admin/milestones/bulk-import
|
|
|
|
Import a set of developmental milestones in one call.
|
|
|
|
- **Auth required:** Yes (admin)
|
|
- **Request body:** An array of milestone objects.
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"count": "number"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Endpoint index (not detailed above)
|
|
|
|
These exist and are in active use; the sections above carry full request and
|
|
response shapes only for the surfaces the frontend touches most. Each group
|
|
names its router, which stays the source of truth.
|
|
|
|
### Clinical Assistant
|
|
|
|
Grounded clinical Q&A over MCP retrieval, plus the image, translation and patient-takehome tools that hang off an answer. Chats are per-user and persisted. `src/routes/clinicalAssistant.js`; see [`clinical-assistant.md`](clinical-assistant.md).
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `POST` | `/api/clinical-assistant/chat` |
|
|
| `GET` | `/api/clinical-assistant/chats` |
|
|
| `POST` | `/api/clinical-assistant/chats` |
|
|
| `DELETE` | `/api/clinical-assistant/chats/:id` |
|
|
| `GET` | `/api/clinical-assistant/chats/:id` |
|
|
| `PATCH` | `/api/clinical-assistant/chats/:id` |
|
|
| `POST` | `/api/clinical-assistant/chat/stream` |
|
|
| `GET` | `/api/clinical-assistant/examples` |
|
|
| `POST` | `/api/clinical-assistant/image` |
|
|
| `GET` | `/api/clinical-assistant/image/jobs` |
|
|
| `POST` | `/api/clinical-assistant/image/jobs` |
|
|
| `GET` | `/api/clinical-assistant/image/jobs/:id` |
|
|
| `GET` | `/api/clinical-assistant/image/jobs/:id/download` |
|
|
| `POST` | `/api/clinical-assistant/patient-takehome` |
|
|
| `POST` | `/api/clinical-assistant/patient-takehome/email` |
|
|
| `GET` | `/api/clinical-assistant/status` |
|
|
| `POST` | `/api/clinical-assistant/translate` |
|
|
| `GET` | `/api/clinical-assistant/translate/languages` |
|
|
|
|
### My Resources
|
|
|
|
Personal teaching material: generate a deck or document, refine it, export it as `pptx`/`docx`/`pdf`/`md`. `src/routes/myResources.js`; see [`my-resources.md`](my-resources.md).
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `GET` | `/api/my-resources` |
|
|
| `POST` | `/api/my-resources/generate` |
|
|
| `DELETE` | `/api/my-resources/:id` |
|
|
| `GET` | `/api/my-resources/:id` |
|
|
| `PUT` | `/api/my-resources/:id` |
|
|
| `GET` | `/api/my-resources/:id/export` |
|
|
| `POST` | `/api/my-resources/:id/refine` |
|
|
| `GET` | `/api/my-resources/image/jobs/:id` |
|
|
| `GET` | `/api/my-resources/options` |
|
|
|
|
### Notes
|
|
|
|
Personal notes with a trash/restore lifecycle, including dictated notes. `src/routes/notes.js`.
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `GET` | `/api/notes` |
|
|
| `POST` | `/api/notes` |
|
|
| `POST` | `/api/notes/from-voice` |
|
|
| `DELETE` | `/api/notes/:id` |
|
|
| `GET` | `/api/notes/:id` |
|
|
| `PUT` | `/api/notes/:id` |
|
|
| `POST` | `/api/notes/:id/restore` |
|
|
| `GET` | `/api/notes/trash` |
|
|
| `POST` | `/api/notes/trash/empty` |
|
|
|
|
### Diagrams
|
|
|
|
Saved diagrams. `src/routes/diagrams.js`.
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `GET` | `/api/diagrams` |
|
|
| `POST` | `/api/diagrams` |
|
|
| `DELETE` | `/api/diagrams/:id` |
|
|
| `GET` | `/api/diagrams/:id` |
|
|
| `PUT` | `/api/diagrams/:id` |
|
|
|
|
### ED Encounters
|
|
|
|
Staged ED notes and the consolidate-to-MDM finalize step. `src/routes/edEncounters.js`; see [`logic/ed-encounters.md`](logic/ed-encounters.md).
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `POST` | `/api/ed-encounters/finalize` |
|
|
| `POST` | `/api/ed-encounters/generate` |
|
|
|
|
### Sessions
|
|
|
|
The signed-in user's own active sessions. `src/routes/sessions.js`.
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `DELETE` | `/api/sessions` |
|
|
| `GET` | `/api/sessions` |
|
|
| `DELETE` | `/api/sessions/:id` |
|
|
|
|
### Registration Invites (Admin)
|
|
|
|
Invite codes for invite-only registration. `DELETE /invites/spent` clears codes that are used or expired-and-not-revoked; a live code is revoked first. `src/routes/adminConfig.js`.
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `GET` | `/api/admin/invites` |
|
|
| `POST` | `/api/admin/invites` |
|
|
| `DELETE` | `/api/admin/invites/:id` |
|
|
| `POST` | `/api/admin/invites/:id/revoke` |
|
|
| `DELETE` | `/api/admin/invites/spent` |
|
|
|
|
### Admin - Documentation Viewer
|
|
|
|
Serves this `docs/` tree inside the Admin panel. `src/routes/adminDocs.js`.
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `GET` | `/api/admin/docs/file` |
|
|
| `GET` | `/api/admin/docs/tree` |
|
|
|
|
### Admin - Web Search
|
|
|
|
Web-search provider configuration and connectivity test.
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `GET` | `/api/admin/websearch` |
|
|
| `PUT` | `/api/admin/websearch` |
|
|
| `POST` | `/api/admin/websearch/test` |
|
|
|
|
### Admin - Image Settings
|
|
|
|
Per-workflow image generation settings.
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `GET` | `/api/admin/image-settings` |
|
|
| `PUT` | `/api/admin/image-settings/:workflow` |
|
|
|
|
### Authentication (additional)
|
|
|
|
`/api/auth/login-code/request` and `/api/auth/login-code/verify` are the
|
|
passwordless sign-in path: a 6-digit code is emailed, hashed at rest, valid
|
|
for 10 minutes, single use, 5 attempts. Password sign-in always remains
|
|
available, so a code that never arrives is never a lockout. The rest manage
|
|
2FA backup codes and password changes. `src/routes/auth.js`,
|
|
`src/utils/loginCodes.js`.
|
|
|
|
| Method | Path |
|
|
|---|---|
|
|
| `POST` | `/api/auth/2fa/backup-codes` |
|
|
| `GET` | `/api/auth/2fa/backup-codes/count` |
|
|
| `POST` | `/api/auth/change-password` |
|
|
| `POST` | `/api/auth/check-password` |
|
|
| `POST` | `/api/auth/login-code/request` |
|
|
| `POST` | `/api/auth/login-code/verify` |
|
|
|
|
Remaining endpoints not listed above are additional admin configuration, model/STT/TTS discovery and test calls, and the per-feature AI helpers (`/api/dont-miss`, `/api/suggest-codes`, `/api/generate-pe-narrative`, `/api/hospital-course-update`, `/api/hospital-course-clarify`, `/api/well-visit/note`, `/api/milestones-data`, `/api/user/features`, `/api/logs/client-error`, `/api/logs/client-event`, `/api/generated-images/:id`, `/api/image-jobs/:workflow`).
|
|
|
|
---
|
|
|
|
## Health
|
|
|
|
### GET /api/health
|
|
|
|
Application health check endpoint.
|
|
|
|
- **Auth required:** No
|
|
- **Response:**
|
|
```json
|
|
{
|
|
"ok": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Metrics
|
|
|
|
### GET /metrics
|
|
|
|
Prometheus scrape endpoint for operational metrics. Metric names use the `ped_ai_` prefix and include HTTP request counters, durations, and in-flight request gauges. Unmatched 404 routes are collapsed under `route="unmatched"` to avoid unbounded path labels.
|
|
|
|
- **Auth required:** No
|
|
- **Response:** Prometheus text exposition format.
|