44 KiB
API Reference
Complete endpoint reference for the PedAI application. All endpoints are prefixed with the application base URL. Unless noted otherwise, authenticated endpoints require a valid JWT token passed via cookie or Authorization: Bearer <token> header.
Table of Contents
- Authentication
- OIDC / SSO
- AI Generation
- Transcription
- Text-to-Speech
- Models
- Encounters
- Memories
- Audio Backups
- Documents
- User Preferences
- Phone Extensions And Pagers
- Nextcloud Integration
- Learning Hub (Public)
- Learning Hub CMS (Moderator+)
- Admin - Users
- Admin - Configuration
- Logs
- Milestones (Admin)
- Health
- 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. Requires Cloudflare Turnstile verification. A verification email is sent on success.
- Auth required: No
- Request body:
{ "name": "string", "email": "string", "password": "string", "turnstileToken": "string" } - Response:
{ "success": true, "message": "Registration successful. Please check your email to verify your account." }
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 tokenstring Email verification token from the link - Response: Redirects to the login page with a success or error message.
POST /api/auth/resend-verification
Resend the email verification link.
- Auth required: No
- Request body:
{ "email": "string" } - Response:
{ "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:
{ "email": "string", "password": "string", "totpCode": "string (optional, required if 2FA is enabled)", "turnstileToken": "string" } - Response:
If 2FA is enabled but{ "success": true, "token": "jwt-string", "user": { "id": "number", "name": "string", "email": "string", "role": "admin | moderator | user" } }totpCodeis not provided:{ "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:
{ "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:
{ "code": "string" } - Response:
{ "success": true, "message": "2FA enabled successfully." }
POST /api/auth/disable-2fa
Disable two-factor authentication. Requires password confirmation.
- Auth required: Yes
- Request body:
{ "password": "string" } - Response:
{ "success": true, "message": "2FA disabled successfully." }
POST /api/auth/forgot-password
Initiate password reset. Sends a reset link to the user's email.
- Auth required: No
- Request body:
{ "email": "string", "turnstileToken": "string" } - Response:
{ "success": true, "message": "If an account exists with that email, a reset link has been sent." }
POST /api/auth/reset-password
Reset the user's password using a valid reset token.
- Auth required: No
- Request body:
{ "token": "string", "password": "string" } - Response:
{ "success": true, "message": "Password reset successfully." }
POST /api/auth/logout
Log out the current user by clearing the JWT cookie.
- Auth required: No
- Request body: None
- Response:
{ "success": true, "message": "Logged out." }
GET /api/auth/me
Retrieve the currently authenticated user's profile.
- Auth required: Yes
- Response:
{ "id": "number", "name": "string", "email": "string", "role": "admin | moderator | user", "twoFactorEnabled": "boolean" }
GET /api/auth/registration-status
Check whether new user registration is enabled on this instance.
- Auth required: No
- Response:
{ "enabled": 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:
{ "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:
{ "transcript": "string", "patientAge": "string", "patientGender": "string", "model": "string", "setting": "string", "physicianMemories": "string (optional)" } - Response: Streamed text (text/event-stream) or JSON with the generated HPI note.
POST /api/generate-hpi-dictation
Generate an HPI note from a physician's dictated summary (same parameters as encounter).
- Auth required: Yes
- Request body:
{ "transcript": "string", "patientAge": "string", "patientGender": "string", "model": "string", "setting": "string", "physicianMemories": "string (optional)" } - Response: Streamed text (text/event-stream) or JSON with the generated HPI note.
POST /api/generate-soap
Generate a SOAP note from a patient encounter transcript.
- Auth required: Yes
- Request body:
{ "transcript": "string", "patientAge": "string", "patientGender": "string", "model": "string", "type": "string", "additionalInstructions": "string (optional)", "physicianMemories": "string (optional)" } - Response: Streamed text (text/event-stream) or JSON with the generated SOAP note.
POST /api/generate-chart-review
Generate a chart review summary from clinical notes.
- Auth required: Yes
- Request body:
{ "notes": "string", "visitType": "string", "model": "string" } - Response: Streamed text or JSON with the chart review.
POST /api/generate-hospital-course
Generate a hospital course summary from clinical notes.
- Auth required: Yes
- Request body:
{ "notes": "string", "patientAge": "string", "patientGender": "string", "model": "string", "format": "string", "physicianMemories": "string (optional)" } - Response: Streamed text or JSON with the hospital course summary.
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:
{ "responses": "object", "patientAge": "string", "model": "string" } - Response: Streamed text or JSON with the SHADESS assessment.
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:
{ "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: Streamed text or JSON with the sick visit note.
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:
{ "noteText": "string", "diagnosis": "string (optional)", "medications": "string (optional)", "patientAge": "string (optional)", "language": "string (optional, defaults to English)", "readingLevel": "string (optional)", "model": "string (optional)" } - Response:
{ "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:
{ "milestones": "object | array", "patientAge": "string", "patientGender": "string", "model": "string" } - Response: Streamed text or JSON with the milestone narrative.
POST /api/generate-milestone-summary
Generate a concise summary from a previously generated milestone narrative.
- Auth required: Yes
- Request body:
{ "narrative": "string", "model": "string" } - Response: Streamed text or JSON with the milestone summary.
POST /api/refine
Refine existing clinical text according to provided instructions.
- Auth required: Yes
- Request body:
{ "currentDocument": "string", "instructions": "string", "sourceContext": "string (optional)", "model": "string" } - Response: Streamed text or JSON with the refined text.
POST /api/shorten
Shorten a block of clinical text while preserving key information.
- Auth required: Yes
- Request body:
{ "document": "string", "model": "string" } - Response: Streamed text or JSON with the shortened text.
POST /api/clarify
Improve clarity and readability of clinical text.
- Auth required: Yes
- Request body:
{ "document": "string", "context": "string (optional)", "model": "string" } - Response: Streamed text or JSON with the clarified text.
Transcription
GET /api/transcribe/status
Check whether speech-to-text transcription is available and which provider is configured.
- Auth required: Yes
- Response:
{ "available": true, "provider": "google | aws | litellm | openai | local | 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 audiofile Audio file to transcribe - Response:
{ "success": true, "text": "string", "provider": "string", "duration": "number (seconds)" }
Text-to-Speech
POST /api/text-to-speech
Convert text to speech. Returns an audio stream.
- Auth required: Yes
- Request body:
{ "text": "string", "voice": "string (optional)" } - Response: Audio stream (
audio/mpeg). - Response headers:
Header Description X-TTS-ProviderThe TTS provider used for synthesis
Models
GET /api/models
List available AI models for the current instance.
- Auth required: Yes
- Response:
{ "provider": "string", "models": [ { "id": "string", "name": "string", "cost": "string", "category": "string" } ], "defaultModel": "string" }
Encounters
GET /api/encounters/saved
List all saved encounters for the authenticated user.
- Auth required: Yes
- Response:
[ { "id": "number", "label": "string", "enc_type": "string", "created_at": "string (ISO 8601)", "updated_at": "string (ISO 8601)" } ]
GET /api/encounters/saved/:id
Retrieve a single saved encounter with full data.
- Auth required: Yes
- Path parameters:
Parameter Type Description idnumber Encounter ID - Response:
{ "id": "number", "label": "string", "enc_type": "string", "transcript": "string", "generated_note": "string", "partial_data": "object | null", "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.
- Auth required: Yes
- Request body:
{ "label": "string", "enc_type": "string", "transcript": "string", "generated_note": "string", "partial_data": "object (optional)", "idempotency_key": "string (optional)" } - Response:
{ "success": true, "id": "number" }
DELETE /api/encounters/saved/:id
Delete a saved encounter.
- Auth required: Yes
- Path parameters:
Parameter Type Description idnumber Encounter ID - Response:
{ "success": true }
Memories
Physician memories are reusable context snippets (preferences, style corrections, common instructions) injected into AI generation prompts.
GET /api/memories
List all memories for the authenticated user. Returns up to 200 entries.
- Auth required: Yes
- Response:
[ { "id": "number", "category": "string", "name": "string", "content": "string", "created_at": "string (ISO 8601)" } ]
POST /api/memories
Create a new memory.
- Auth required: Yes
- Request body:
{ "category": "string", "name": "string", "content": "string" } - Response:
{ "success": true, "id": "number" }
PUT /api/memories/:id
Update an existing memory.
- Auth required: Yes
- Path parameters:
Parameter Type Description idnumber Memory ID - Request body:
{ "category": "string", "name": "string", "content": "string" } - Response:
{ "success": true }
DELETE /api/memories/:id
Delete a memory.
- Auth required: Yes
- Path parameters:
Parameter Type Description idnumber Memory ID - Response:
{ "success": true }
GET /api/memories/context
Retrieve all memories formatted for injection into AI generation prompts.
- Auth required: Yes
- Response:
{ "context": "string" }
POST /api/memories/correction
Automatically save a style correction as a memory. Used when the physician corrects AI output.
- Auth required: Yes
- Request body:
{ "section": "string", "original_snippet": "string", "corrected_snippet": "string" } - Response:
{ "success": true, "id": "number" }
Audio Backups
Temporary audio backup storage with automatic 24-hour expiry.
POST /api/audio-backups
Upload an audio backup. The file is gzip-compressed on the server.
- Auth required: Yes
- Content-Type:
multipart/form-data - Form fields:
Field Type Description audiofile Audio file to back up - Response:
{ "success": true, "id": "number" }
GET /api/audio-backups
List all audio backups for the authenticated user.
- Auth required: Yes
- Response:
[ { "id": "number", "filename": "string", "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 idnumber 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 idnumber Audio backup ID - Response:
{ "success": true }
Documents
S3-backed document storage for clinical files.
GET /api/documents
List all documents for the authenticated user.
- Auth required: Yes
- Response:
[ { "id": "number", "filename": "string", "mimetype": "string", "size": "number", "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, WebP), Word documents (.doc, .docx), plain text (.txt), CSV (.csv)
- Form fields:
Field Type Description filefile Document to upload - Response:
{ "success": true, "id": "number", "filename": "string" }
GET /api/documents/:id/download
Download a document.
- Auth required: Yes
- Path parameters:
Parameter Type Description idnumber Document ID - Response: Binary file stream with appropriate content-type and content-disposition headers.
DELETE /api/documents/:id
Delete a document from S3 storage.
- Auth required: Yes
- Path parameters:
Parameter Type Description idnumber Document ID - Response:
{ "success": true }
User Preferences
GET /api/user/preferences
Get the authenticated user's preferences.
- Auth required: Yes
- Response:
{ "stt_model": "string", "tts_voice": "string" }
POST /api/user/preferences
Save user preferences.
- Auth required: Yes
- Request body:
{ "stt_model": "string", "tts_voice": "string" } - Response:
{ "success": true }
GET /api/user/preferences/options
List available STT models and TTS voices that the user can choose from.
- Auth required: Yes
- Response:
{ "sttModels": [ { "id": "string", "name": "string" } ], "ttsVoices": [ { "id": "string", "name": "string" } ] }
POST /api/user/webdav-path
Save the user's preferred WebDAV learning content path.
- Auth required: Yes
- Request body:
{ "path": "string" } - Response:
{ "success": true }
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 trashstring 1ortruereturns trashed entries instead of active entries.qstring Case-insensitive search over location, name, number, and notes. - Response:
{ "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:
{ "location": "ED", "name": "Charge Nurse", "number": "1234", "type": "extension", "notes": "Optional note" } - Response:
{ "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 idnumber Entry ID. - Request body: Same fields as
POST /api/extensions. - Response:
{ "success": true }
DELETE /api/extensions/:id
Move an active entry to trash. This is a soft delete.
- Auth required: Yes
- Response:
{ "success": true }
POST /api/extensions/:id/restore
Restore a trashed entry.
- Auth required: Yes
- Response:
{ "success": true }
DELETE /api/extensions/:id/purge
Permanently delete a trashed entry.
- Auth required: Yes
- Response:
{ "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-Typeapplication/zipContent-DispositionAttachment filename. X-Export-CountNumber of exported active entries. - JSON file shape inside ZIP:
{ "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
itemsandoptions.{ "items": [ { "location": "ED", "name": "Charge Nurse", "number": "1234", "type": "extension", "notes": "Optional note" } ], "options": { "restoreTrashed": true, "importPossibleDuplicates": false } } - Response:
{ "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:
{ "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-datawith fieldfile. - 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-datawith fieldfile. - 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:
{ "url": "string", "username": "string", "password": "string" } - Response:
{ "success": true, "message": "Connected to Nextcloud." }
POST /api/nextcloud/export
Export text content to the connected Nextcloud instance.
- Auth required: Yes
- Request body:
{ "text": "string", "title": "string" } - Response:
{ "success": true, "path": "string" }
POST /api/nextcloud/disconnect
Disconnect the user's Nextcloud integration.
- Auth required: Yes
- Request body: None
- Response:
{ "success": true, "message": "Disconnected from Nextcloud." }
Learning Hub (Public)
Public-facing learning content endpoints. Authentication is required to track progress and submit quizzes.
GET /api/learning/categories
List all learning content categories.
- Auth required: Yes
- Response:
[ { "id": "number", "name": "string", "slug": "string", "description": "string" } ]
GET /api/learning/feed
Get a paginated feed of learning content.
- Auth required: Yes
- Query parameters:
Parameter Type Default Description limitnumber 20 Items per page offsetnumber 0 Pagination offset - Response:
[ { "id": "number", "title": "string", "slug": "string", "summary": "string", "category": "string", "created_at": "string (ISO 8601)" } ]
GET /api/learning/category/:slug
Get all learning content within a specific category.
- Auth required: Yes
- Path parameters:
Parameter Type Description slugstring Category slug - Response: Array of content items in the category.
GET /api/learning/content/:slug
Get a single piece of learning content, including quiz questions, answer options, and the user's progress.
- Auth required: Yes
- Path parameters:
Parameter Type Description slugstring Content slug - Response:
{ "id": "number", "title": "string", "slug": "string", "body": "string (markdown)", "category": "object", "questions": [ { "id": "number", "text": "string", "options": [ { "id": "number", "text": "string" } ] } ], "progress": { "completed": "boolean", "score": "number | null" } }
GET /api/learning/content/:slug/slides
Render Marp-formatted markdown content as HTML presentation slides.
- Auth required: Yes
- Path parameters:
Parameter Type Description slugstring Content slug - Response: HTML presentation content.
POST /api/learning/submit-quiz
Submit quiz answers for a piece of learning content.
- Auth required: Yes
- Request body:
{ "contentId": "number", "answers": [ { "questionId": "number", "optionIds": ["number"] } ] } - Response:
{ "success": true, "score": "number", "total": "number", "results": [ { "questionId": "number", "correct": "boolean" } ] }
GET /api/learning/search
Keyword-based search across learning content.
- Auth required: Yes
- Query parameters:
Parameter Type Description qstring Search query - Response: Array of matching content items.
GET /api/learning/search/semantic
Semantic (vector-based) search across learning content using embeddings.
- Auth required: Yes
- Query parameters:
Parameter Type Description qstring Search query - Response: Array of matching content items ranked by semantic similarity.
GET /api/learning/search/hybrid
Combined keyword and semantic search for best-of-both-worlds results.
- Auth required: Yes
- Query parameters:
Parameter Type Description qstring Search query - Response: Array of matching content items with combined ranking.
Learning Hub CMS (Moderator+)
Content management endpoints for learning content. Requires moderator or admin role.
GET /api/admin/learning/categories
List all learning categories (admin view).
- Auth required: Yes (moderator+)
- Response: Array of category objects.
POST /api/admin/learning/categories
Create a new learning category.
- Auth required: Yes (moderator+)
- Request body:
{ "name": "string", "slug": "string", "description": "string" } - Response:
{ "success": true, "id": "number" }
PUT /api/admin/learning/categories/:id
Update a learning category.
- Auth required: Yes (moderator+)
- Path parameters:
Parameter Type Description idnumber Category ID - Request body:
{ "name": "string", "slug": "string", "description": "string" } - Response:
{ "success": true }
DELETE /api/admin/learning/categories/:id
Delete a learning category.
- Auth required: Yes (moderator+)
- Path parameters:
Parameter Type Description idnumber Category ID - Response:
{ "success": true }
GET /api/admin/learning/content
List all learning content (admin view, includes unpublished).
- Auth required: Yes (moderator+)
- Response: Array of content objects.
POST /api/admin/learning/content
Create new learning content.
- Auth required: Yes (moderator+)
- Request body:
{ "title": "string", "slug": "string", "body": "string (markdown)", "categoryId": "number", "questions": "array (optional)" } - Response:
{ "success": true, "id": "number" }
GET /api/admin/learning/content/:id
Get a single content item for editing.
- Auth required: Yes (moderator+)
- Path parameters:
Parameter Type Description idnumber Content ID - Response: Full content object with questions and metadata.
PUT /api/admin/learning/content/:id
Update existing learning content.
- Auth required: Yes (moderator+)
- Path parameters:
Parameter Type Description idnumber Content ID - Request body:
{ "title": "string", "slug": "string", "body": "string (markdown)", "categoryId": "number", "questions": "array (optional)" } - Response:
{ "success": true }
DELETE /api/admin/learning/content/:id
Delete learning content.
- Auth required: Yes (moderator+)
- Path parameters:
Parameter Type Description idnumber Content ID - Response:
{ "success": true }
POST /api/admin/learning/ai-generate
Generate learning content or presentations using AI. Accepts either multipart form data (with file uploads) or JSON.
- Auth required: Yes (moderator+)
- Content-Type:
multipart/form-dataorapplication/json - Request body (JSON):
{ "topic": "string", "type": "article | presentation", "model": "string" } - Request body (multipart): Same fields plus uploaded reference files.
- Response:
{ "success": true, "content": "string (markdown)" }
POST /api/admin/learning/ai-refine
Refine learning content body text using AI.
- Auth required: Yes (moderator+)
- Request body:
{ "body": "string", "instructions": "string", "model": "string" } - Response:
{ "success": true, "content": "string" }
POST /api/admin/learning/preview-slides
Preview Marp-formatted markdown as rendered presentation slides.
- Auth required: Yes (moderator+)
- Request body:
{ "markdown": "string" } - Response:
{ "css": "string", "slides": ["string (HTML)"] }
POST /api/admin/learning/generate-pptx
Generate a PowerPoint file from Marp markdown.
- Auth required: Yes (moderator+)
- Request body:
{ "markdown": "string", "title": "string" } - Response: Binary
.pptxfile download.
GET /api/admin/learning/webdav-browse
Browse files on the connected WebDAV/Nextcloud server.
- Auth required: Yes (moderator+)
- Query parameters:
Parameter Type Description pathstring Directory path to browse - Response: Array of file/directory entries.
GET /api/admin/learning/stats
Get learning hub statistics (content counts, quiz completion rates, etc.).
- Auth required: Yes (moderator+)
- Response:
{ "totalContent": "number", "totalCategories": "number", "totalQuizSubmissions": "number", "averageScore": "number" }
Admin - Users
Requires admin role.
GET /api/admin/users
List all registered users.
- Auth required: Yes (admin)
- Response:
[ { "id": "number", "name": "string", "email": "string", "role": "string", "verified": "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 idnumber User ID - Response:
{ "id": "number", "name": "string", "email": "string", "role": "string", "verified": "boolean", "disabled": "boolean", "stats": { "totalGenerations": "number", "totalTranscriptions": "number", "lastActive": "string (ISO 8601)" } }
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 idnumber User ID - Response:
{ "success": true }
POST /api/admin/users/:id/disable
Disable a user account, preventing login.
- Auth required: Yes (admin)
- Path parameters:
Parameter Type Description idnumber User ID - Response:
{ "success": true }
POST /api/admin/users/:id/enable
Re-enable a previously disabled user account.
- Auth required: Yes (admin)
- Path parameters:
Parameter Type Description idnumber User ID - Response:
{ "success": true }
Admin - Configuration
Requires admin role unless noted otherwise.
GET /api/admin/config/announcement
Get the current announcement banner. This endpoint is public and does not require authentication.
- Auth required: No
- Response:
{ "announcement": "string | null" }
GET /api/admin/config
Get all application configuration settings.
- Auth required: Yes (admin)
- Response: Object containing all configuration key-value pairs.
POST /api/admin/config
Update application configuration settings.
- Auth required: Yes (admin)
- Request body: Object with configuration key-value pairs to update.
- Response:
{ "success": true }
POST /api/admin/config/test-email
Send a test email to verify SMTP configuration.
- Auth required: Yes (admin)
- Request body:
{ "to": "string (email address)" } - Response:
{ "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
Save AI prompt template overrides.
- Auth required: Yes (admin)
- Request body: Object mapping prompt keys to new values.
- Response:
{ "success": true }
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 keystring Prompt template key - Response:
{ "success": true }
POST /api/admin/config/reset-defaults
Reset all configuration settings to their default values.
- Auth required: Yes (admin)
- Response:
{ "success": true }
GET /api/admin/config/smtp/status
Check the current SMTP configuration status.
- Auth required: Yes (admin)
- Response:
{ "configured": "boolean", "host": "string", "port": "number" }
POST /api/admin/config/smtp/update
Update SMTP email configuration.
- Auth required: Yes (admin)
- Request body:
{ "host": "string", "port": "number", "username": "string", "password": "string", "from": "string" } - Response:
{ "success": true }
POST /api/admin/config/registration
Update registration settings (enable/disable new registrations).
- Auth required: Yes (admin)
- Request body:
{ "enabled": "boolean" } - Response:
{ "success": true }
GET /api/admin/config/oidc
Get the current OIDC/SSO configuration.
- Auth required: Yes (admin)
- Response:
{ "enabled": "boolean", "clientId": "string", "issuerUrl": "string", "buttonLabel": "string", "disableLocalAuth": "boolean" }
POST /api/admin/config/oidc
Update the OIDC/SSO configuration.
- Auth required: Yes (admin)
- Request body:
{ "enabled": "boolean", "clientId": "string", "clientSecret": "string", "issuerUrl": "string", "buttonLabel": "string", "disableLocalAuth": "boolean" } - Response:
{ "success": true }
GET /api/admin/config/models
List all AI models with their enabled/disabled status.
- Auth required: Yes (admin)
- Response:
[ { "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:
{ "modelId": "string", "enabled": "boolean" } - Response:
{ "success": true }
PUT /api/admin/config/models/default
Set the default AI model for all users.
- Auth required: Yes (admin)
- Request body:
{ "modelId": "string" } - Response:
{ "success": true }
POST /api/admin/config/models/custom
Add a custom AI model definition.
- Auth required: Yes (admin)
- Request body:
{ "id": "string", "name": "string", "category": "string" } - Response:
{ "success": true }
GET /api/admin/config/models/discover
Discover available models from the configured AI provider.
- Auth required: Yes (admin)
- Response:
{ "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:
{ "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/seed
Seed the database with the default set of developmental milestones.
- Auth required: Yes (admin)
- Request body: None
- Response:
{ "success": true, "count": "number" }
Health
GET /api/health
Application health check endpoint.
- Auth required: No
- Response:
{ "status": "ok", "provider": "string", "uptime": "number (seconds)" }
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.