{"openapi":"3.1.0","info":{"title":"Omni API","version":"0.0.51","description":"Weather, time, service status, authenticated email delivery, speech generation, caption jobs, reasoning, and OCR."},"servers":[{"url":"https://omni-api.lndotech.com"}],"tags":[{"name":"Platform","description":"Health, version, status, and time."},{"name":"Weather","description":"Cached weather and managed watch locations."},{"name":"Email","description":"Authenticated immediate or delayed email delivery."},{"name":"Speech","description":"Orpheus speech models, voices, and authenticated audio generation."},{"name":"Captions","description":"Persistent, scoped transcription jobs for uploaded audio and video."},{"name":"Reasoning","description":"Scoped local-model answers with separately authorized reasoning traces."},{"name":"OCR","description":"Scoped text extraction from directly uploaded images."},{"name":"Admin","description":"Authenticated operational state."},{"name":"Compatibility","description":"Deprecated aliases retained for existing clients."}],"paths":{"/openapi.json":{"get":{"tags":["Platform"],"summary":"Published OpenAPI document","operationId":"getOpenApiDocument","responses":{"200":{"description":"OpenAPI 3.1 document."}}}},"/api/v1/health":{"get":{"tags":["Platform"],"summary":"Service liveness","operationId":"getHealth","responses":{"200":{"description":"Service is running."}}}},"/api/v1/version":{"get":{"tags":["Platform"],"summary":"Published build information","operationId":"getVersion","responses":{"200":{"description":"Version metadata."}}}},"/api/v1/status":{"get":{"tags":["Platform"],"summary":"Redacted feature status","operationId":"getStatus","responses":{"200":{"description":"Feature availability without infrastructure details."}}}},"/api/v1/time":{"get":{"tags":["Platform"],"summary":"Current server time","operationId":"getTime","responses":{"200":{"description":"Current time in ISO, locale, and Unix millisecond formats."}}}},"/api/v1/weather":{"get":{"tags":["Weather"],"summary":"Full weather for all watched locations","operationId":"getAllWeather","responses":{"200":{"description":"Weather records."},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/weather/summary":{"get":{"tags":["Weather"],"summary":"Current conditions for all watched locations","operationId":"getWeatherSummary","responses":{"200":{"description":"Weather summaries."},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/weather/watchlist":{"get":{"tags":["Weather"],"summary":"List watched locations","operationId":"getWeatherWatchlist","responses":{"200":{"description":"Watchlist and refresh policy."}}},"post":{"tags":["Weather"],"summary":"Add a watched location","operationId":"addWeatherLocation","security":[{"adminKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["location"],"properties":{"location":{"type":"string","minLength":1,"maxLength":120}}},"example":{"location":"Boston, MA"}}}},"responses":{"200":{"description":"Location already existed."},"201":{"description":"Location added."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/weather/{id}":{"get":{"tags":["Weather"],"summary":"Weather for one watched location","operationId":"getWeatherById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":0}},{"name":"fresh","in":"query","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Full weather record."},"404":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/email/messages":{"post":{"tags":["Email"],"summary":"Send or schedule an email","operationId":"sendEmail","security":[{"adminKey":[]},{"emailKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailMessage"},"example":{"to":"recipient@example.com","subject":"Service update","body":"The requested operation completed.","delaySeconds":0}}}},"responses":{"200":{"description":"Email sent or scheduled."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tts/models":{"get":{"tags":["Speech"],"summary":"Available speech models","operationId":"getTtsModels","responses":{"200":{"description":"OpenAI-compatible model list."}}}},"/api/v1/tts/voices":{"get":{"tags":["Speech"],"summary":"Available voices","operationId":"getTtsVoices","responses":{"200":{"description":"Default voice and configured voices."}}}},"/api/v1/tts/speech":{"post":{"tags":["Speech"],"summary":"Generate speech audio","operationId":"generateSpeech","security":[{"adminKey":[]},{"scopedKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeechRequest"}}}},"responses":{"200":{"description":"Generated WAV or raw PCM audio.","content":{"audio/wav":{"schema":{"type":"string","format":"binary"}},"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/captions/status":{"get":{"tags":["Captions"],"summary":"Protected caption-engine and queue status","operationId":"getCaptionsStatus","security":[{"adminKey":[]},{"scopedKey":[]}],"responses":{"200":{"description":"Redacted caption runtime, queue, and limit state."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/captions/jobs":{"get":{"tags":["Captions"],"summary":"List owned caption jobs","operationId":"listCaptionJobs","security":[{"adminKey":[]},{"scopedKey":[]}],"responses":{"200":{"description":"Caption jobs owned by this key; the root key can see every job."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Captions"],"summary":"Upload media and queue caption generation","operationId":"createCaptionJob","security":[{"adminKey":[]},{"scopedKey":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"},"profile":{"type":"string","enum":["fast","accurate"]},"language":{"type":"string","default":"auto","maxLength":24},"initialPrompt":{"type":"string","maxLength":2000}}}}}},"responses":{"202":{"description":"Caption job queued."},"400":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/captions/jobs/{id}":{"get":{"tags":["Captions"],"summary":"Get owned caption job status","operationId":"getCaptionJob","security":[{"adminKey":[]},{"scopedKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Current caption job state and available artifacts."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Captions"],"summary":"Delete an owned inactive caption job","operationId":"deleteCaptionJob","security":[{"adminKey":[]},{"scopedKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Caption job and retained files deleted."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/captions/jobs/{id}/actions":{"post":{"tags":["Captions"],"summary":"Cancel or retry an owned caption job","operationId":"actOnCaptionJob","security":[{"adminKey":[]},{"scopedKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["cancel","retry"]}},"additionalProperties":false}}}},"responses":{"202":{"description":"Caption job action accepted."},"400":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/captions/jobs/{id}/artifacts/{format}":{"get":{"tags":["Captions"],"summary":"Download an owned caption artifact","operationId":"downloadCaptionArtifact","security":[{"adminKey":[]},{"scopedKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"path","required":true,"schema":{"type":"string","enum":["vtt","srt","txt","json"]}}],"responses":{"200":{"description":"Generated caption artifact."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/reasoning/status":{"get":{"tags":["Reasoning"],"summary":"Protected reasoning runtime status","operationId":"getReasoningStatus","security":[{"adminKey":[]},{"scopedKey":[]}],"responses":{"200":{"description":"Redacted local runtime and queue state."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/reasoning/models":{"get":{"tags":["Reasoning"],"summary":"Allowed reasoning models","operationId":"getReasoningModels","security":[{"adminKey":[]},{"scopedKey":[]}],"responses":{"200":{"description":"Allowlisted local reasoning models, availability, and server-configured context windows."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/reasoning/responses":{"post":{"tags":["Reasoning"],"summary":"Generate a reasoned response","description":"Requires reasoning.responses.create. Selecting a model marked with safetyProfile unlocked also requires reasoning.unlocked.use. Set responseFormat to json when an integration requires syntactically valid JSON rather than relying on prompt wording.","operationId":"createReasoningResponse","security":[{"adminKey":[]},{"scopedKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReasoningRequest"}}}},"responses":{"200":{"description":"Final answer, usage, and an authorized optional thinking trace."},"400":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/ocr/status":{"get":{"tags":["OCR"],"summary":"Protected OCR runtime status","operationId":"getOcrStatus","security":[{"adminKey":[]},{"scopedKey":[]}],"responses":{"200":{"description":"Redacted local vision runtime and queue state."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/ocr/models":{"get":{"tags":["OCR"],"summary":"Allowed OCR models","operationId":"getOcrModels","security":[{"adminKey":[]},{"scopedKey":[]}],"responses":{"200":{"description":"Allowlisted local vision models, availability, packaging, and server-configured context windows."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/ocr/extractions":{"post":{"tags":["OCR"],"summary":"Extract text from an image","operationId":"createOcrExtraction","security":[{"adminKey":[]},{"scopedKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OcrRequest"}}}},"responses":{"200":{"description":"Extracted text, image metadata, and token usage."},"400":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/admin/status":{"get":{"tags":["Admin"],"summary":"Protected operational status","operationId":"getAdminStatus","security":[{"adminKey":[]}],"responses":{"200":{"description":"Detailed service-owned state."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/health":{"get":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy health alias","operationId":"getLegacyHealth","responses":{"200":{"description":"Service is running."}}}},"/time":{"get":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy time alias","operationId":"getLegacyTime","responses":{"200":{"description":"Current service time."}}}},"/weather":{"get":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy full weather list","operationId":"getLegacyWeather","responses":{"200":{"description":"Legacy weather records."},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/weather/all":{"get":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy weather summaries","operationId":"getLegacyWeatherSummary","responses":{"200":{"description":"Legacy weather summary records."},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/weather/watchlist":{"get":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy weather watchlist","operationId":"getLegacyWeatherWatchlist","responses":{"200":{"description":"Legacy watchlist contract."}}},"post":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy watchlist update","operationId":"addLegacyWeatherLocation","security":[{"adminKey":[]}],"responses":{"200":{"description":"Location already existed."},"201":{"description":"Location added."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/weather/{id}":{"get":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy weather by ID","operationId":"getLegacyWeatherById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"Legacy weather record."},"404":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/weather/fresh/{id}":{"get":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy fresh weather by ID","operationId":"getLegacyFreshWeatherById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"Legacy freshly requested weather record."},"404":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sendemail":{"post":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy email delivery alias","operationId":"sendLegacyEmail","security":[{"adminKey":[]},{"emailKey":[]},{"legacyEmailKey":[]}],"responses":{"200":{"description":"Email sent or scheduled."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/audio/speech":{"post":{"tags":["Compatibility"],"deprecated":true,"summary":"Legacy TTS synthesis route","operationId":"generateLegacySpeech","security":[{"adminKey":[]},{"scopedKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeechRequest"}}}},"responses":{"200":{"description":"Generated audio."},"401":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"adminKey":{"type":"http","scheme":"bearer","description":"Omni administrator key."},"scopedKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Least-privilege Omni or imported legacy TTS key."},"emailKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Email-only API key."},"legacyEmailKey":{"type":"apiKey","in":"header","name":"X-Auth","description":"Deprecated email-only header."}},"schemas":{"SpeechRequest":{"type":"object","required":["input"],"additionalProperties":false,"properties":{"model":{"type":"string","description":"Compatibility hint; the selected voice determines the routed model."},"input":{"type":"string","minLength":1,"maxLength":4000},"voice":{"type":"string","maxLength":80,"default":"tara"},"response_format":{"type":"string","enum":["wav","pcm"],"default":"wav"},"speed":{"type":"number","minimum":0.25,"maximum":4,"default":1,"description":"Accepted for compatibility; the current engine reports whether it was applied."}}},"ReasoningRequest":{"type":"object","required":["prompt"],"additionalProperties":false,"properties":{"prompt":{"type":"string","minLength":1,"maxLength":96000},"system":{"type":"string","maxLength":32000},"model":{"type":"string","description":"Must be in the server-side reasoning allowlist. Context size is selected safely by the server for the model. Unlocked test models additionally require reasoning.unlocked.use."},"includeThinking":{"type":"boolean","default":false,"description":"Also requires reasoning.traces.read."},"responseFormat":{"type":"string","enum":["text","json"],"default":"text","description":"Use json for Ollama-constrained, server-validated JSON. Omni performs at most one internal repair attempt and returns the parsed value as outputJson."},"maxTokens":{"type":"integer","minimum":64,"maximum":8192,"default":1024,"description":"Maximum generation budget, including thinking and the final answer. The selected model context window may impose a smaller practical budget for large inputs."},"temperature":{"type":"number","minimum":0,"maximum":2,"default":0.2}}},"OcrRequest":{"type":"object","required":["image"],"additionalProperties":false,"properties":{"image":{"type":"string","format":"byte","description":"Base64 image bytes or a matching image data URL. Remote URLs are not accepted."},"mimeType":{"type":"string","enum":["image/png","image/jpeg","image/webp","image/gif"]},"prompt":{"type":"string","maxLength":4000},"model":{"type":"string","description":"Must be in the server-side OCR allowlist. The list can include general vision models and document-specialized PaddleOCR-VL."}}},"EmailMessage":{"type":"object","required":["to","subject","body"],"properties":{"to":{"type":"string","format":"email"},"subject":{"type":"string","minLength":1,"maxLength":200},"body":{"type":"string","minLength":1,"maxLength":20480},"delaySeconds":{"type":"integer","minimum":0,"maximum":86400,"default":0}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","requestId"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"requestId":{"type":"string","format":"uuid"}}}}}}}}