{"openapi": "3.1.0", "info": {"title": "DEML Learning Platform API", "version": "2.0.0", "description": "Identity, account, billing, learning interactions, and sealed FORJD handoff.\n\nAuthenticate with a Firebase session cookie (browser) or a `deml_\u2026` API key (Bearer / `X-API-Key`) on headless integration routes. Sealed ingest and processing execute in FORJD via the mapped tenant service credential."}, "paths": {"/api/v1/health": {"get": {"operationId": "config_api_api_health", "summary": "Api Health", "parameters": [], "responses": {"200": {"description": "OK"}}, "description": "Liveness \u2014 process is up (Fly health checks)."}}, "/api/v1/ready": {"get": {"operationId": "config_api_api_ready", "summary": "Api Ready", "parameters": [], "responses": {"200": {"description": "OK"}}, "description": "Readiness \u2014 Postgres reachable; FORJD credentials present (not a live FORJD probe)."}}, "/api/v1/auth/register": {"get": {"operationId": "config_api_auth_api_register_health", "summary": "Api Register Health", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessSchema"}}}}}, "description": "Health probe for monitors; user registration is handled client-side via Firebase."}}, "/api/v1/auth/user": {"get": {"operationId": "config_api_auth_api_user", "summary": "Api User", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessSchema"}}}}}}}, "/api/v1/auth/delete-account": {"delete": {"operationId": "config_api_auth_api_delete_account", "summary": "Api Delete Account", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DeleteAccountOut"}}}}}}}, "/api/v1/auth/api-keys/generate": {"post": {"operationId": "config_api_auth_generate_api_key", "summary": "Generate API Key", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/APIKeyGenerateOut"}}}}}, "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/APIKeyGenerateIn"}}}, "required": true}}}, "/api/v1/auth/api-keys": {"get": {"operationId": "config_api_auth_list_api_keys", "summary": "List API Keys", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/APIKeyOut"}, "title": "Response", "type": "array"}}}}}}}, "/api/v1/auth/api-keys/{key_id}": {"delete": {"operationId": "config_api_auth_delete_api_key", "summary": "Revoke API Key", "parameters": [{"in": "path", "name": "key_id", "schema": {"title": "Key Id", "type": "string"}, "required": true}], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessSchema"}}}}}}}, "/api/v1/auth/handoff/generate": {"post": {"operationId": "config_api_auth_generate_handoff_token", "summary": "Generate cross-domain handoff token", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HandoffGenerateOut"}}}}}, "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/HandoffGenerateIn"}}}, "required": true}}}, "/api/v1/auth/handoff/verify": {"post": {"operationId": "config_api_auth_verify_handoff_token", "summary": "Verify one-time handoff token", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DesktopAuthOut"}}}}}, "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/HandoffVerifyIn"}}}, "required": true}}}, "/api/v1/auth/desktop/session": {"post": {"operationId": "config_api_auth_validate_desktop_session", "summary": "Validate a native desktop session", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DesktopAuthOut"}}}}}, "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/DesktopSessionIn"}}}, "required": true}}}, "/api/v1/auth/sessions": {"post": {"operationId": "config_api_auth_register_session_endpoint", "summary": "Register browser session", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRegisterOut"}}}}}, "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRegisterIn"}}}, "required": true}}, "get": {"operationId": "config_api_auth_list_sessions_endpoint", "summary": "List active sessions", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"items": {"$ref": "#/components/schemas/SessionOut"}, "title": "Response", "type": "array"}}}}}}}, "/api/v1/auth/sessions/{session_id}": {"delete": {"operationId": "config_api_auth_revoke_session_endpoint", "summary": "Revoke session", "parameters": [{"in": "path", "name": "session_id", "schema": {"title": "Session Id", "type": "string"}, "required": true}], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessSchema"}}}}}}}, "/api/v1/auth/logout": {"post": {"operationId": "config_api_auth_logout_session_endpoint", "summary": "Sign out server session", "parameters": [], "responses": {"200": {"description": "OK", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessSchema"}}}}}, "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/LogoutIn"}}}, "required": true}}}, "/api/v1/users/consent": {"post": {"operationId": "monitor_api_record_consent", "summary": "Record Consent", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["Users"], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/ConsentIn"}}}, "required": true}}}, "/api/v1/users/newsletter": {"post": {"operationId": "monitor_api_subscribe", "summary": "Subscribe", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["Users"], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/NewsletterIn"}}}, "required": true}}}, "/api/v1/agent/report-issue": {"post": {"operationId": "agent_api_report_issue", "summary": "Report Issue", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["Interactions"], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/IssueReportPayload"}}}, "required": true}}}, "/api/v1/billing/create-checkout-session": {"post": {"operationId": "billing_api_create_checkout_session", "summary": "Create Checkout Session", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["Billing"]}}, "/api/v1/billing/webhook": {"post": {"operationId": "billing_api_stripe_webhook", "summary": "Stripe Webhook", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["Billing"]}}, "/api/v1/billing/sync": {"post": {"operationId": "billing_api_sync_subscription", "summary": "Sync Subscription", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["Billing"]}}, "/api/v1/billing/cancel-subscription": {"post": {"operationId": "billing_api_cancel_subscription", "summary": "Cancel Subscription", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["Billing"]}}, "/api/v1/billing/resume-subscription": {"post": {"operationId": "billing_api_resume_subscription", "summary": "Resume Subscription", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["Billing"]}}, "/api/v1/forjd/health": {"get": {"operationId": "forjd_api_health", "summary": "Health", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["FORJD"]}}, "/api/v1/forjd/ingest": {"post": {"operationId": "forjd_api_ingest", "summary": "Ingest", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["FORJD"], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SealedEvent"}}}, "required": true}}}, "/api/v1/forjd/ingest/events:batch": {"post": {"operationId": "forjd_api_ingest_batch", "summary": "Ingest Batch", "parameters": [], "responses": {"200": {"description": "OK"}}, "tags": ["FORJD"], "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/SealedEventBatch"}}}, "required": true}}}}, "components": {"schemas": {"SuccessSchema": {"properties": {"status": {"title": "Status", "type": "string"}, "user": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "User"}, "user_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "User Id"}, "role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}}, "required": ["status"], "title": "SuccessSchema", "type": "object"}, "DeleteAccountOut": {"properties": {"status": {"title": "Status", "type": "string"}, "job_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Job Id"}, "completed": {"default": false, "title": "Completed", "type": "boolean"}}, "required": ["status"], "title": "DeleteAccountOut", "type": "object"}, "APIKeyGenerateOut": {"properties": {"status": {"title": "Status", "type": "string"}, "name": {"title": "Name", "type": "string"}, "key": {"title": "Key", "type": "string"}, "prefix": {"title": "Prefix", "type": "string"}}, "required": ["status", "name", "key", "prefix"], "title": "APIKeyGenerateOut", "type": "object"}, "APIKeyGenerateIn": {"properties": {"name": {"default": "Integration Key", "title": "Name", "type": "string"}}, "title": "APIKeyGenerateIn", "type": "object"}, "APIKeyOut": {"properties": {"id": {"title": "Id", "type": "string"}, "name": {"title": "Name", "type": "string"}, "prefix": {"title": "Prefix", "type": "string"}, "created_at": {"title": "Created At", "type": "string"}}, "required": ["id", "name", "prefix", "created_at"], "title": "APIKeyOut", "type": "object"}, "HandoffGenerateOut": {"properties": {"status": {"title": "Status", "type": "string"}, "token": {"title": "Token", "type": "string"}}, "required": ["status", "token"], "title": "HandoffGenerateOut", "type": "object"}, "HandoffGenerateIn": {"properties": {"code_challenge": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Code Challenge"}, "client_name": {"default": "web", "title": "Client Name", "type": "string"}}, "title": "HandoffGenerateIn", "type": "object"}, "DesktopAuthOut": {"properties": {"status": {"title": "Status", "type": "string"}, "user": {"title": "User", "type": "string"}, "email": {"title": "Email", "type": "string"}, "user_id": {"title": "User Id", "type": "integer"}, "role": {"title": "Role", "type": "string"}, "desktop_token": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Desktop Token"}}, "required": ["status", "user", "email", "user_id", "role"], "title": "DesktopAuthOut", "type": "object"}, "HandoffVerifyIn": {"properties": {"token": {"title": "Token", "type": "string"}, "code_verifier": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Code Verifier"}}, "required": ["token"], "title": "HandoffVerifyIn", "type": "object"}, "DesktopSessionIn": {"properties": {"desktop_token": {"title": "Desktop Token", "type": "string"}}, "required": ["desktop_token"], "title": "DesktopSessionIn", "type": "object"}, "SessionRegisterOut": {"properties": {"status": {"title": "Status", "type": "string"}, "session_id": {"title": "Session Id", "type": "string"}}, "required": ["status", "session_id"], "title": "SessionRegisterOut", "type": "object"}, "SessionRegisterIn": {"properties": {"session_id": {"title": "Session Id", "type": "string"}, "user_agent": {"default": "", "title": "User Agent", "type": "string"}}, "required": ["session_id"], "title": "SessionRegisterIn", "type": "object"}, "SessionOut": {"properties": {"session_id": {"title": "Session Id", "type": "string"}, "user_agent": {"default": "", "title": "User Agent", "type": "string"}, "ip": {"default": "", "title": "Ip", "type": "string"}, "created_at": {"default": 0, "title": "Created At", "type": "integer"}, "last_seen": {"default": 0, "title": "Last Seen", "type": "integer"}}, "required": ["session_id"], "title": "SessionOut", "type": "object"}, "LogoutIn": {"properties": {"session_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Session Id"}, "revoke_all": {"default": false, "title": "Revoke All", "type": "boolean"}}, "title": "LogoutIn", "type": "object"}, "ConsentIn": {"properties": {"necessary": {"default": true, "title": "Necessary", "type": "boolean"}, "analytical": {"default": false, "title": "Analytical", "type": "boolean"}, "marketing": {"default": false, "title": "Marketing", "type": "boolean"}}, "title": "ConsentIn", "type": "object"}, "NewsletterIn": {"properties": {"email": {"title": "Email", "type": "string"}, "consent_accepted": {"title": "Consent Accepted", "type": "boolean"}}, "required": ["email", "consent_accepted"], "title": "NewsletterIn", "type": "object"}, "IssueReportPayload": {"properties": {"client_report_id": {"anyOf": [{"format": "uuid", "type": "string"}, {"type": "null"}], "title": "Client Report Id"}, "user_description": {"title": "User Description", "type": "string"}, "telemetry_context": {"additionalProperties": true, "default": {}, "title": "Telemetry Context", "type": "object"}}, "required": ["user_description"], "title": "IssueReportPayload", "type": "object"}, "EncryptedEnvelope": {"additionalProperties": false, "properties": {"algo": {"const": "aes-256-gcm", "default": "aes-256-gcm", "title": "Algo", "type": "string"}, "key_id": {"maxLength": 256, "minLength": 1, "title": "Key Id", "type": "string"}, "nonce": {"maxLength": 64, "minLength": 8, "title": "Nonce", "type": "string"}, "ciphertext": {"maxLength": 1048576, "minLength": 24, "title": "Ciphertext", "type": "string"}, "ciphertext_sha256": {"pattern": "^[0-9a-f]{64}$", "title": "Ciphertext Sha256", "type": "string"}, "ratchet_header": {"anyOf": [{"maxLength": 8192, "type": "string"}, {"type": "null"}], "title": "Ratchet Header"}}, "required": ["key_id", "nonce", "ciphertext", "ciphertext_sha256"], "title": "EncryptedEnvelope", "type": "object"}, "EncryptionOptions": {"additionalProperties": false, "properties": {"mode": {"const": "e2ee", "default": "e2ee", "title": "Mode", "type": "string"}, "algo": {"const": "aes-256-gcm", "default": "aes-256-gcm", "title": "Algo", "type": "string"}}, "title": "EncryptionOptions", "type": "object"}, "SealedEvent": {"additionalProperties": false, "description": "The only event shape DEML may forward to FORJD today.", "properties": {"tenant_id": {"format": "uuid", "title": "Tenant Id", "type": "string"}, "client_event_id": {"maxLength": 128, "minLength": 1, "title": "Client Event Id", "type": "string"}, "content_type": {"const": "application/forjd-telemetry+v1", "default": "application/forjd-telemetry+v1", "title": "Content Type", "type": "string"}, "event_type": {"default": "deml.metric", "enum": ["deml.metric", "deml.alert"], "title": "Event Type", "type": "string"}, "schema_version": {"default": 1, "maximum": 1000, "minimum": 1, "title": "Schema Version", "type": "integer"}, "workflow_id": {"const": "deml_telemetry", "default": "deml_telemetry", "title": "Workflow Id", "type": "string"}, "encryption": {"allOf": [{"$ref": "#/components/schemas/EncryptionOptions"}]}, "envelope": {"$ref": "#/components/schemas/EncryptedEnvelope"}, "metadata": {"additionalProperties": true, "title": "Metadata", "type": "object"}}, "required": ["tenant_id", "client_event_id", "envelope"], "title": "SealedEvent", "type": "object"}, "SealedEventBatch": {"additionalProperties": false, "properties": {"events": {"items": {"$ref": "#/components/schemas/SealedEvent"}, "maxItems": 25, "minItems": 1, "title": "Events", "type": "array"}}, "required": ["events"], "title": "SealedEventBatch", "type": "object"}}}, "servers": []}