{"openapi":"3.1.0","info":{"title":"RelayOn API","version":"1.0.0","description":"One RelayOn API key for text, OCR, transcription and speech synthesis, with OpenAI-compatible text APIs.\n\n## Accounts and workspaces\nSigned-in playground requests select a personal or organization account with `X-Account-ID`: use `personal` or an organization ID. Provider keys, credit, files and playground history belong to that account. Account limits apply independently of workspace limits. Use `X-Workspace-ID` for workspace requests; omitting both selects the default workspace. Never send both headers. Bearer API keys always use their assigned workspace and cannot select an account with this header. Personal and organization balances remain separate.\n\n## Provider keys and billing\nEligible provider keys in the selected account are tried first. Your provider bills that usage directly, with no RelayOn routing fee. Where supported, published paid capacity uses your RelayOn balance if no usable key exists or safe key retries are exhausted. Access rules and spending limits still apply. Requests are not replayed after output starts or processing becomes uncertain. Legacy ar/ routes do not use paid fallback. Every public canonical model has published paid pricing.\n\n## Organizations\nOrganizations group shared workspaces. Owners and admins manage workspace resources; members can send inference; viewers can read history. Invitations appear in the recipient’s account and expire after seven days. Only owners manage administrators, organization names and archival. Shared workspaces use a separate organization credit balance; account guardrails and privacy remain owner-controlled. Suspended or removed creators cannot use organization API keys. Organization archival blocks new work but preserves reads.\n\n## Request Plugins\nAll plugins default off. Use `plugins: [{id: \"response-healing\"}]` for non-streaming JSON repair, or enable tool-output-compression, context-compression (Headroom), and output-compression. Request overrides API key overrides workspace defaults. Empty arrays inherit defaults. X-RelayOn-Plugins reports outcomes, added latency and text token estimates. Compression failures preserve original input. Unknown or invalid plugins return 400 invalid_plugins.\n\n## Inference controls\nAccount and workspace guardrails combine with API-key restrictions. Workspace routing preferences apply only to BYOK autoroutes and cannot enable paid fallback.\n\n## Errors\n\nErrors contain an `error` object with `message`, `type`, `param`, and `code`. Messages come from RelayOn; provider details are kept in operator diagnostics. Authenticate before model or capacity checks.\n\n| HTTP status | Code | Applies to | Meaning |\n| --- | --- | --- | --- |\n| 400 | invalid_json, model_required, invalid_model_id, wrong_model_kind | Text and OCR | Correct the request body or model selection. |\n| 400 | invalid_document | OCR | Provide a document URL, data URI, or uploaded file ID. |\n| 401 | auth_required | Text and OCR | Supply a valid RelayOn API key. |\n| 400 | invalid_controls | Controls | Correct the settings. |\n| 403 | guardrail_violation | Text and OCR | Account or workspace policy blocks the effective request. |\n| 403 | model_not_allowed, provider_not_allowed | Text and OCR | The API key does not allow this model or provider. |\n| 402 | insufficient_credits, model_not_priced | Operated models | Add credits or select a priced model. |\n| 404 | model_not_found | Text and OCR | The requested model is unavailable or unknown. |\n| 404 | file_not_found, job_not_found | OCR | The file or job does not exist or belongs to another account. |\n| 413 | document_too_large | OCR | The request document exceeds the configured size limit. |\n| 422 | encrypted_pdf | OCR | Encrypted PDFs are unsupported. Upload an unencrypted PDF, including files that open without asking for a password but still use encryption. |\n| 429 | Request-limit code | Text and OCR | RelayOn API key request limit exceeded; honor Retry-After. |\n| 500 | no_text_extracted | OCR | No readable text was extracted. Try a clearer scan or another document. |\n| 422 | unsupported_option, context_limit_exceeded | Text | Adjust model options, shorten input, or lower max_tokens. |\n| 422 | unsupported_format, unprocessable_document, too_many_pages | OCR | Upload a supported, valid document within the page limit. |\n| 400 | invalid_request_parameters | Text | The model rejected request parameters. Check messages and generation options. |\n| 502 | upstream_connection_error | Text and OCR | The connection to the generation service failed. |\n| 503 | upstream_unavailable | Text and OCR | The generation service is temporarily unavailable. |\n| 504 | upstream_timeout | Text and OCR | The generation service did not respond before the deadline. |\n| 500 | internal_error | Text and OCR | RelayOn could not complete the request. Provider details are masked. |\n| 500 | internal_error | OCR jobs | RelayOn could not complete internal job processing. |\n| 503 | no_capacity | Text and OCR | No capacity is available for this model right now. Honor Retry-After. |\n| 503 | state_unavailable | Text and OCR | Request capacity is temporarily unavailable. Honor Retry-After. |\n\nStreaming text errors use the same safe error object in a `data:` SSE event. Once streaming starts, the HTTP status cannot change. Synchronous OCR makes one attempt. Async OCR retries transient failures internally; document validation errors are not retried. A failed async job is returned by polling with HTTP 200, `status: failed`, and `error.message` / `error.code`; it is not billed. Encrypted PDFs cannot be processed, even when they open without a password. Encrypted-document errors do not lower service uptime or provider routing reliability. Uploaded files may be stored before OCR validation, so a successful file upload does not guarantee that OCR can read the document.","contact":{"email":"contact@tensorcode.co.id"}},"servers":[{"url":"/","description":"Current instance"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"RelayOn API key (ro_live_...)"},"sessionAuth":{"type":"apiKey","in":"cookie","name":"relayon_session","description":"Signed-in account session; API keys cannot manage privacy."}},"schemas":{"OcrDocument":{"oneOf":[{"type":"object","required":["type","url"],"properties":{"type":{"type":"string","enum":["document_url","image_url"]},"url":{"type":"string","description":"An http(s) url, or a base64 data uri such as data:application/pdf;base64,... capped at 20MB"}}},{"type":"object","required":["type","file_id"],"properties":{"type":{"type":"string","enum":["file_id"]},"file_id":{"type":"string","description":"The id returned by POST /v1/files"}}}]},"SttRequest":{"type":"object","required":["model","audio"],"additionalProperties":false,"properties":{"provider":{"$ref":"#/components/schemas/ProviderSelection"},"model":{"type":"string","example":"relayon/stt"},"audio":{"oneOf":[{"type":"object","required":["type","file_id"],"additionalProperties":false,"properties":{"type":{"type":"string","enum":["file_id"]},"file_id":{"type":"string"}}},{"type":"object","required":["type","url"],"additionalProperties":false,"properties":{"type":{"type":"string","enum":["audio_url"]},"url":{"type":"string","format":"uri","description":"Public HTTPS audio. Private destinations and unsafe redirects are blocked; bytes are stored once for pool-safe retries."}}}]},"language":{"type":"string","nullable":true,"description":"A code from the selected model’s stt.languages list. Omit for automatic detection when stt.auto_language is true. Unsupported hints return HTTP 422 unsupported_language; there is no automatic fallback. A client may retry without language after this explicit rejection if detection is supported and acceptable, but must not resubmit an accepted or uncertain job."},"timestamps":{"type":"string","enum":["none","word","segment"],"default":"none","description":"Supported timestamp options and speaker requirements depend on the selected model."},"diarize":{"type":"boolean","default":false},"channel_mode":{"type":"string","enum":["mixdown"]},"response_format":{"type":"string","enum":["json"]}}},"SttWord":{"type":"object","required":["start","end","text","channel"],"properties":{"start":{"type":"number","minimum":0,"description":"Seconds from audio start"},"end":{"type":"number","minimum":0},"text":{"type":"string"},"channel":{"type":"integer","enum":[0]},"confidence":{"type":"number","minimum":0,"maximum":1},"speaker":{"type":"string","example":"speaker_0"}}},"SttResult":{"type":"object","required":["model","text","audio_duration_seconds","usage"],"properties":{"model":{"type":"string"},"text":{"type":"string"},"language":{"type":"string"},"audio_duration_seconds":{"type":"number","exclusiveMinimum":true,"minimum":0},"no_speech":{"type":"boolean","description":"True when the transcription result reports no speech. Check result.no_speech === true instead of inferring silence from word count; words may be absent when timestamps were not requested. Valid silence is successful and billable."},"words":{"type":"array","items":{"$ref":"#/components/schemas/SttWord"}},"segments":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/SttWord"},{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}}]}},"usage":{"type":"object","required":["audio_seconds","metering_basis","channels_processed"],"properties":{"audio_seconds":{"type":"number"},"billable_seconds":{"type":"number","description":"Present for duration-metered models."},"input_audio_tokens":{"type":"integer","minimum":0},"input_tokens":{"type":"integer","minimum":0,"description":"Provider-reported text control tokens, separate from audio tokens."},"output_tokens":{"type":"integer","minimum":0},"metering_basis":{"type":"string","enum":["audio_duration","tokens"]},"channels_processed":{"type":"integer","enum":[1]}}}}},"SttJob":{"type":"object","required":["id","object","status","model","created_at"],"properties":{"id":{"type":"string","pattern":"^sttjob_[a-f0-9]{32}$"},"object":{"type":"string","enum":["audio.transcription.job"]},"model":{"type":"string"},"status":{"type":"string","enum":["queued","processing","uncertain","completed","failed","cancelled"],"description":"Poll queued, processing and uncertain. Completed, failed and cancelled are terminal. On completed, read result. On failed, read error. These differ from OCR running/succeeded. An uncertain job needs reconciliation; keep its ID and do not resubmit."},"created_at":{"type":"string","format":"date-time"},"finished_at":{"type":"string","format":"date-time","nullable":true},"cancel_requested":{"type":"boolean"},"result":{"$ref":"#/components/schemas/SttResult"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"type":{"type":"string"},"param":{"type":"string","nullable":true}}}}},"TtsDescriptor":{"type":"object","properties":{"auto_language":{"type":"boolean","description":"Automatic language selection; languages can be empty when enabled."},"languages":{"type":"array","items":{"type":"string"}},"voices":{"type":"array","items":{"type":"string"}},"formats":{"type":"array","items":{"type":"string","enum":["mp3","wav","opus"]}},"max_input_bytes":{"type":"integer"},"speeds":{"type":"array","items":{"type":"number"}}}},"SttDescriptor":{"type":"object","properties":{"languages":{"type":"array","items":{"type":"string"}},"auto_language":{"type":"boolean"},"max_audio_seconds":{"type":"number","description":"Duration limit, when present. Absent means no duration limit."},"channel_modes":{"type":"array","items":{"type":"string","enum":["mixdown"]}},"metering_basis":{"type":"string","enum":["audio_duration","tokens"]},"max_annotated_audio_seconds":{"type":"number","description":"Lower duration limit for requests with timestamps or speaker labels, when present."},"timestamps":{"type":"array","items":{"type":"string","enum":["none","word","segment"]}},"diarization":{"type":"boolean"},"segment_requires_diarization":{"type":"boolean"},"max_audio_bytes":{"type":"integer"},"max_input_channels":{"type":"integer"}}},"OcrRequest":{"type":"object","required":["model","document"],"properties":{"provider":{"$ref":"#/components/schemas/ProviderSelection"},"model":{"type":"string","example":"relayon/ocr"},"document":{"$ref":"#/components/schemas/OcrDocument"},"pages":{"type":"array","items":{"type":"integer"},"description":"Zero indexed page numbers to read, omitted means every page. PDFs only, and you are billed for the pages selected rather than the whole document. The selected pages come back as one entry rather than one entry per page."},"table_format":{"type":"string","enum":["markdown","html"],"description":"An engine that cannot honour it fails the request with a RelayOn upstream_error"},"include_images":{"type":"boolean","default":false,"description":"An engine that cannot honour it fails the request with a RelayOn upstream_error"},"async":{"type":"boolean","default":false,"description":"Returns 202 with a job to poll instead of waiting for the pages"}}},"OcrResponse":{"type":"object","properties":{"model":{"type":"string"},"pages":{"type":"array","description":"What the engine could return. An engine that reads a document in one pass returns a single entry carrying all of it, while usage.pages_processed still reports the true count, so the two can differ.","items":{"type":"object","properties":{"index":{"type":"integer"},"markdown":{"type":"string"}}}},"usage":{"type":"object","properties":{"pages_processed":{"type":"integer","description":"What you are billed for"}}}}},"OcrJob":{"type":"object","properties":{"id":{"type":"string","example":"ocrjob_4964f4174e0e248a5cc043e7f3b21ac5"},"object":{"type":"string","example":"ocr.job"},"status":{"type":"string","enum":["queued","running","succeeded","failed"]},"model":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"started_at":{"type":"string","format":"date-time","nullable":true},"finished_at":{"type":"string","format":"date-time","nullable":true},"pages":{"type":"integer","nullable":true,"description":"What was billed, once the job finished"},"result":{"$ref":"#/components/schemas/OcrResponse"},"error":{"type":"object","properties":{"message":{"type":"string"},"code":{"type":"string"}}}}},"FileObject":{"type":"object","properties":{"id":{"type":"string","example":"file_8f96360be4d2a854b97d06e6b3c8142e"},"object":{"type":"string","example":"file"},"filename":{"type":"string","nullable":true},"content_type":{"type":"string"},"bytes":{"type":"integer"},"purpose":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"ChatMessage":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","enum":["system","user","assistant"]},"content":{"type":"string"}}},"InferencePolicy":{"type":"object","additionalProperties":false,"required":["allowOperated","allowTools","models","providers"],"properties":{"allowOperated":{"type":"boolean"},"allowTools":{"type":"boolean"},"maxOutputTokens":{"type":["integer","null"],"minimum":1,"maximum":1000000},"models":{"type":"array","maxItems":500,"items":{"type":"string"},"description":"Exact public IDs, or ar/slug to allow its eligible BYOK providers. Empty means unrestricted at this scope."},"providers":{"type":"array","maxItems":500,"items":{"type":"string"}}}},"RoutingPreferences":{"type":"object","additionalProperties":false,"required":["sort","allowFallbacks","providers"],"properties":{"sort":{"type":"string","enum":["throughput","latency"]},"allowFallbacks":{"type":"boolean"},"providers":{"type":"array","maxItems":500,"items":{"type":"string"},"description":"Provider IDs in priority order. Unlisted providers follow by ranking; restrictions always apply."}}},"RequestPlugin":{"type":"object","required":["id"],"additionalProperties":false,"properties":{"id":{"type":"string","enum":["response-healing","tool-output-compression","context-compression","output-compression"]},"enabled":{"type":"boolean","default":true},"mode":{"type":"string","enum":["conservative"]},"style":{"type":"string","enum":["concise"]}}},"ProviderSelection":{"type":"object","additionalProperties":false,"properties":{"only":{"type":"array","minItems":1,"maxItems":50,"uniqueItems":true,"items":{"type":"string"},"description":"Strict allowlist of serving provider IDs."},"order":{"type":"array","minItems":1,"maxItems":50,"uniqueItems":true,"items":{"type":"string"},"description":"Preferred provider order within each credential stage. Other eligible providers may follow."},"allow_fallbacks":{"type":"boolean","default":true,"description":"False keeps both credential stages on the first selected provider."}}},"ChatCompletionRequest":{"type":"object","required":["messages"],"oneOf":[{"required":["model"],"not":{"required":["models"]}},{"required":["models"],"not":{"required":["model"]}}],"properties":{"plugins":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/RequestPlugin"},"description":"Per-plugin overrides of API key and workspace defaults. All workspace defaults are disabled. Empty arrays inherit defaults."},"model":{"type":"string","example":"deepseek/deepseek-v4.1-flash","description":"An accepted lab/model ID. Existing legacy IDs retain their established behavior; an explicit provider object opts into canonical routing."},"models":{"type":"array","minItems":1,"maxItems":5,"items":{"type":"string"},"description":"Explicit ordered canonical model fallback. Do not also send model. Fallback stops after output or uncertain processing."},"provider":{"$ref":"#/components/schemas/ProviderSelection"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/ChatMessage"}},"stream":{"type":"boolean","default":false},"temperature":{"type":"number"},"max_tokens":{"type":"integer"},"reasoning_effort":{"type":"string","enum":["none","low","medium","high","xhigh"]}}},"ChatCompletionResponse":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["chat.completion"]},"model":{"type":"string"},"choices":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"message":{"$ref":"#/components/schemas/ChatMessage"},"finish_reason":{"type":"string","enum":["stop","length"]}}}},"usage":{"type":"object","properties":{"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"total_tokens":{"type":"integer"}}}}},"ResponsesRequest":{"type":"object","required":["model","input"],"properties":{"plugins":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/RequestPlugin"},"description":"Per-plugin overrides of API key and workspace defaults. All workspace defaults are disabled. Empty arrays inherit defaults."},"model":{"type":"string","example":"deepseek-v4.1-flash"},"input":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"object"}}]},"instructions":{"type":"string"},"stream":{"type":"boolean","default":false},"reasoning":{"type":"object","properties":{"effort":{"type":"string"},"summary":{"type":"string"}}}}},"MessagesRequest":{"type":"object","required":["model","messages"],"properties":{"plugins":{"type":"array","maxItems":4,"items":{"$ref":"#/components/schemas/RequestPlugin"},"description":"Per-plugin overrides of API key and workspace defaults. All workspace defaults are disabled. Empty arrays inherit defaults."},"model":{"type":"string","example":"deepseek-v4.1-flash"},"max_tokens":{"type":"integer","example":1024},"system":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string"},"content":{"type":"string"}}}},"stream":{"type":"boolean","default":false}}},"ModelObject":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["model"]},"owned_by":{"type":"string"},"capabilities":{"type":"array","items":{"type":"string"}},"stt":{"$ref":"#/components/schemas/SttDescriptor"},"tts":{"$ref":"#/components/schemas/TtsDescriptor"},"serving":{"$ref":"#/components/schemas/PublishedOffering"}}},"PublishedOffering":{"type":"object","description":"Published provider availability and pricing. Temporary capacity loss preserves enabled modes, identity and prices. BYOK availability indicates route support; the caller still needs an authorized provider key. Legacy models may omit this object.","properties":{"modes":{"type":"array","items":{"type":"object","properties":{"mode":{"type":"string","enum":["byok","provided"]},"available":{"type":"boolean"}}}},"prices":{"type":"array","description":"Selected provider rates charged to your RelayOn balance, in USD millionths per unitQuantity. Base rates apply off-peak when a peak schedule exists. Empty for BYOK-only providers.","items":{"$ref":"#/components/schemas/MeterPrice"}},"usageMeters":{"type":"array","items":{"type":"string"}},"publishedAt":{"type":["string","null"],"format":"date-time","description":"RelayOn publication time, distinct from upstream model release date."}}},"MeterPrice":{"type":"object","required":["meter","rateMicro","unitQuantity","currency","effectiveFrom"],"properties":{"meter":{"type":"string"},"rateMicro":{"type":"integer","minimum":0},"unitQuantity":{"type":"integer","minimum":1},"currency":{"type":"string","enum":["USD"]},"effectiveFrom":{"type":"string","format":"date-time"},"tiers":{"type":"array","description":"Ascending thresholds. The last exceeded threshold selects the rate for the whole request, using total input including cached tokens. Output and cache rates also use input length.","items":{"$ref":"#/components/schemas/InputPriceTier"}},"peak":{"type":"object","description":"Optional daily schedule specific to this provider and price version. Any overlap from upstream submission through completion charges peak rates for the entire request, including streams. Otherwise base rates and tiers apply.","required":["timeZone","startMinute","endMinute","rateMicro"],"properties":{"timeZone":{"type":"string","description":"IANA timezone used to evaluate local clock time, including daylight saving where applicable."},"startMinute":{"type":"integer","minimum":0,"maximum":1439,"description":"Inclusive start, in minutes after local midnight."},"endMinute":{"type":"integer","minimum":0,"maximum":1439,"description":"Exclusive end, in minutes after local midnight. Must differ from startMinute; an earlier end crosses midnight."},"rateMicro":{"type":"integer","minimum":0},"tiers":{"type":"array","description":"Independent peak-period input thresholds; omission means a flat peak rate.","items":{"$ref":"#/components/schemas/InputPriceTier"}}}}}},"InputPriceTier":{"type":"object","required":["aboveInputTokens","rateMicro"],"properties":{"aboveInputTokens":{"type":"integer","minimum":1,"description":"Exclusive total input-token threshold. K denotes 1,000 tokens."},"rateMicro":{"type":"integer","minimum":0}}},"ComboStep":{"type":"object","required":["model"],"properties":{"model":{"type":"string","example":"deepseek-v4-flash"},"isEnabled":{"type":"boolean","default":true}}},"Combo":{"type":"object","properties":{"id":{"type":"string"},"publicId":{"type":"string","example":"combo/coding-fast"},"slug":{"type":"string","example":"coding-fast"},"name":{"type":"string"},"isEnabled":{"type":"boolean"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/ComboStep"}}}},"ComboCreateRequest":{"type":"object","required":["slug","name","steps"],"properties":{"slug":{"type":"string","example":"coding-fast"},"name":{"type":"string","example":"Coding fast"},"isEnabled":{"type":"boolean","default":true},"steps":{"type":"array","items":{"$ref":"#/components/schemas/ComboStep"}}}},"PrivacySettings":{"type":"object","properties":{"log_content":{"type":"boolean","default":true},"retention_days":{"type":"integer","minimum":1,"maximum":30,"default":30},"maximum_retention_days":{"type":"integer","minimum":0,"maximum":30,"description":"Server ceiling; zero disables capture."},"deleted_before":{"type":"string","format":"date-time","nullable":true}}},"UsageDetail":{"allOf":[{"$ref":"#/components/schemas/UsageRecord"},{"type":"object","properties":{"content_logging":{"type":"object","properties":{"state":{"type":"string","enum":["available","disabled","deleted","expired","not_captured"]},"expires_at":{"type":"string","format":"date-time"}}},"upstream_status":{"type":"integer","nullable":true},"payloads":{"type":"object","description":"Redacted request and response bodies. All body fields are null when disabled, deleted or expired.","properties":{"client_request":{"type":"object","nullable":true,"additionalProperties":true},"upstream_request":{"type":"object","nullable":true,"additionalProperties":true},"upstream_response":{"type":"object","nullable":true,"additionalProperties":true},"client_response":{"type":"object","nullable":true,"additionalProperties":true}}}}}]},"UsageRecord":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["usage.record"]},"model":{"type":"string"},"provider_id":{"type":"string","nullable":true},"connection_id":{"type":"string","nullable":true},"api_key_id":{"type":"string","nullable":true},"status":{"type":"string","enum":["success","partial","error","cache_hit","accepted"]},"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"total_tokens":{"type":"integer"},"credits":{"type":"number"},"latency_ms":{"type":"integer","nullable":true,"description":"Total request duration in milliseconds, including queueing and retries. Retained for compatibility; this is not TTFT."},"ttft_ms":{"type":"integer","nullable":true,"description":"Successful text provider attempt to first nonempty reasoning, answer or tool-call output."},"generation_ms":{"type":"integer","nullable":true,"description":"First generated output to last generated output on a completed successful text request."},"upstream_response_ms":{"type":"integer","nullable":true,"description":"Time until the document service responds; excludes document processing."},"queue_wait_ms":{"type":"integer","nullable":true,"description":"Asynchronous OCR job creation to worker start."},"created_at":{"type":"string","format":"date-time"},"combo":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"winning_model":{"type":"string","nullable":true},"attempts":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"providerId":{"type":"string","nullable":true},"error":{"type":"string","nullable":true},"retryable":{"type":"boolean"}}}}}}}},"UsageSummary":{"type":"object","properties":{"object":{"type":"string","enum":["usage.summary"]},"window":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}}},"requests":{"type":"integer","description":"All requests in the selected window, including pending and failed requests."},"success":{"type":"integer"},"error":{"type":"integer"},"partial":{"type":"integer"},"cache_hit":{"type":"integer"},"accepted":{"type":"integer"},"tokens":{"type":"object","properties":{"prompt":{"type":"integer"},"completion":{"type":"integer"},"total":{"type":"integer"},"cached":{"type":"integer"}}},"units":{"type":"object","properties":{"text_tokens":{"type":"integer"},"ocr_pages":{"type":"number"},"stt_seconds":{"type":"number"},"tts_characters":{"type":"number"}}},"cost":{"type":"object","properties":{"upstream_micro":{"type":"integer"},"charge_micro":{"type":"integer"}}},"latency_ms":{"type":"object","properties":{"avg":{"type":"number","nullable":true},"p50":{"type":"number","nullable":true},"p95":{"type":"number","nullable":true}}},"ttft_ms":{"type":"object","properties":{"avg":{"type":"number","nullable":true},"p50":{"type":"number","nullable":true},"p95":{"type":"number","nullable":true},"samples":{"type":"integer"}}},"generation_ms":{"type":"object","properties":{"avg":{"type":"number","nullable":true},"p50":{"type":"number","nullable":true},"p95":{"type":"number","nullable":true},"samples":{"type":"integer"}}},"upstream_response_ms":{"type":"object","properties":{"avg":{"type":"number","nullable":true},"p50":{"type":"number","nullable":true},"p95":{"type":"number","nullable":true},"samples":{"type":"integer"}}},"queue_wait_ms":{"type":"object","properties":{"avg":{"type":"number","nullable":true},"p50":{"type":"number","nullable":true},"p95":{"type":"number","nullable":true},"samples":{"type":"integer"}}},"generation_samples":{"type":"integer"},"tps":{"type":"number","description":"Sum of completion tokens minus one per eligible request divided by summed first-to-last output time. Includes completed successful requests with at least two output tokens and positive generation time; excludes cache, errors, partial and historical unmeasured requests. Returns zero with no samples; inspect generation_samples."},"tpm":{"type":"number","description":"Average total tokens per minute across the selected window."},"rpm":{"type":"number","description":"Average requests per minute across the selected window, not the count in the most recent minute."}}},"UsageTimeseriesPoint":{"type":"object","properties":{"t":{"type":"string","format":"date-time"},"requests":{"type":"integer"},"tokens":{"type":"integer"},"units":{"type":"object","properties":{"text_tokens":{"type":"integer"},"ocr_pages":{"type":"number"},"stt_seconds":{"type":"number"},"tts_characters":{"type":"number"}}},"errors":{"type":"integer"},"latency_ms_avg":{"type":"number","nullable":true,"description":"Average total request duration."},"ttft_ms_avg":{"type":"number","nullable":true},"upstream_response_ms_avg":{"type":"number","nullable":true},"ttft_samples":{"type":"integer"},"upstream_response_samples":{"type":"integer"}}},"UsageBreakdownRow":{"type":"object","properties":{"key":{"type":"string"},"requests":{"type":"integer"},"tokens":{"type":"integer"},"units":{"type":"object","properties":{"text_tokens":{"type":"integer"},"ocr_pages":{"type":"number"},"stt_seconds":{"type":"number"},"tts_characters":{"type":"number"}}},"errors":{"type":"integer"}}}}},"paths":{"/api/organizations":{"get":{"summary":"List Organizations","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}},"post":{"summary":"Create Organization","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":80}}}}}},"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/organizations/invitations":{"get":{"summary":"List Your Pending Invitations","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/organizations/invitations/{id}/accept":{"post":{"summary":"Accept Your Invitation","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/organizations/{id}":{"patch":{"summary":"Rename, Archive or Restore Organization (Owner)","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"isArchived":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/organizations/{id}/balance":{"get":{"summary":"Read Shared Available Balance","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/organizations/{id}/members":{"get":{"summary":"List Organization Members","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/organizations/{id}/members/{userId}":{"patch":{"summary":"Change Member Role (Administrator Roles Require Owner)","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"role":{"type":"string","enum":["admin","member","viewer"]}}}}}},"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}},"delete":{"summary":"Remove Member and Disable Their Organization Keys","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/organizations/{id}/invitations":{"get":{"summary":"List Organization Invitations (Owner or Admin)","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}},"post":{"summary":"Invite Member (Owner or Admin)","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["admin","member","viewer"]}}}}}},"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/organizations/{id}/invitations/{invitationId}":{"delete":{"summary":"Revoke Invitation (Owner or Admin)","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"invitationId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/organizations/{id}/audit":{"get":{"summary":"Read Organization Audit History (Owner or Admin)","tags":["Organizations"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":15}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Successful organization operation; role-specific access applies."},"201":{"description":"Organization or invitation created."},"400":{"description":"Invalid input."},"401":{"description":"Session required."},"403":{"description":"Role cannot perform this action, or organization is archived."},"404":{"description":"Organization, member or invitation unavailable to this session."},"409":{"description":"User is already a member."}}}},"/api/workspaces/{id}/plugins":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Read Workspace Plugin Defaults","tags":["Workspaces"],"security":[{"sessionAuth":[]}],"responses":{"200":{"description":"Plugin defaults and Headroom availability"},"403":{"description":"Workspace access denied"}}},"put":{"summary":"Replace Workspace Plugin Defaults","tags":["Workspaces"],"security":[{"sessionAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plugins"],"properties":{"plugins":{"type":"array","items":{"$ref":"#/components/schemas/RequestPlugin"}}}}}}},"responses":{"200":{"description":"Saved defaults"},"400":{"description":"Invalid plugin configuration"},"403":{"description":"Owner or admin required; archived workspace rejected"}}}},"/api/api-keys/{id}/plugins":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Read API Key Plugin Overrides","tags":["API Keys"],"security":[{"sessionAuth":[]}],"responses":{"200":{"description":"Key overrides, workspace defaults and Headroom availability"},"404":{"description":"Key not found in this workspace"}}},"put":{"summary":"Replace API Key Plugin Overrides","tags":["API Keys"],"security":[{"sessionAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plugins"],"properties":{"plugins":{"type":"array","items":{"$ref":"#/components/schemas/RequestPlugin"}}}}}}},"responses":{"200":{"description":"Saved overrides; omitted plugins inherit workspace defaults"},"400":{"description":"Invalid plugin configuration"},"403":{"description":"Owner or admin required"},"404":{"description":"Key not found in this workspace"}}}},"/v1/chat/completions":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"post":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Chat Completions","description":"OpenAI-compatible chat completions endpoint. Supports streaming.","tags":["Chat"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}}},"responses":{"200":{"description":"Completion response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionResponse"}}}},"400":{"description":"Invalid request body or model selection"},"401":{"description":"Authentication required: auth_required"},"402":{"description":"Insufficient credits or model_not_priced"},"403":{"description":"Model, provider or request capability is blocked by API-key, account or workspace restrictions."},"404":{"description":"Model not found"},"422":{"description":"Model options, context size or document validation failed"},"429":{"description":"Rate limit exceeded"},"500":{"description":"RelayOn internal_error; provider details are masked"},"502":{"description":"Connection to the generation service failed (upstream_connection_error)"},"503":{"description":"No model capacity (no_capacity), temporarily unavailable capacity (state_unavailable), or unavailable generation service (upstream_unavailable); honor Retry-After","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before retrying"}}},"504":{"description":"Generation service deadline exceeded (upstream_timeout)"}}}},"/v1/responses":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"post":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Responses API","description":"OpenAI Responses API format. Requests are translated internally to Chat Completions and back.","tags":["Responses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsesRequest"}}}},"responses":{"200":{"description":"Response object"},"400":{"description":"Invalid request body or model selection"},"401":{"description":"Authentication required: auth_required"},"402":{"description":"Insufficient credits or model_not_priced"},"403":{"description":"Model, provider or request capability is blocked by API-key, account or workspace restrictions."},"404":{"description":"Model not found"},"422":{"description":"Model options, context size or document validation failed"},"429":{"description":"RelayOn request limit exceeded"},"500":{"description":"RelayOn internal_error; provider details are masked"},"502":{"description":"Connection to the generation service failed (upstream_connection_error)"},"503":{"description":"No model capacity (no_capacity), temporarily unavailable capacity (state_unavailable), or unavailable generation service (upstream_unavailable); honor Retry-After","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before retrying"}}},"504":{"description":"Generation service deadline exceeded (upstream_timeout)"}}}},"/v1/messages":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"post":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Messages (Anthropic)","description":"Anthropic Messages API format. Translated internally to chat completions.","tags":["Messages"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagesRequest"}}}},"responses":{"200":{"description":"Anthropic message response"},"400":{"description":"Invalid request body or model selection"},"401":{"description":"Authentication required: auth_required"},"402":{"description":"Insufficient credits or model_not_priced"},"403":{"description":"Model, provider or request capability is blocked by API-key, account or workspace restrictions."},"404":{"description":"Model not found"},"422":{"description":"Model options, context size or document validation failed"},"429":{"description":"RelayOn request limit exceeded"},"500":{"description":"RelayOn internal_error; provider details are masked"},"502":{"description":"Connection to the generation service failed (upstream_connection_error)"},"503":{"description":"No model capacity (no_capacity), temporarily unavailable capacity (state_unavailable), or unavailable generation service (upstream_unavailable); honor Retry-After","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before retrying"}}},"504":{"description":"Generation service deadline exceeded (upstream_timeout)"}}}},"/v1/audio/speech":{"post":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Synthesize speech","tags":["TTS"],"description":"Returns audio bytes for an enabled speech provider. Provider requests try eligible account BYOK keys first, then published RelayOn-provided capacity after safe rejections or when no usable key exists. Paid fallback requires access and spend approval; ambiguous acceptance never falls back. Token-metered providers reserve an upper bound and settle measured usage at admitted rates. Uncertain submissions require reconciliation and must not be resubmitted with a new idempotency key.","parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":200},"description":"Provider TTS: printable non-space ASCII key scoped to the caller and account or workspace. Reuse the same key and request after a connection failure. Completed requests replay retained audio when content logging and retention allow it; replay never generates or charges again. Missing, expired or deleted audio returns 410."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["model","input","voice"],"additionalProperties":false,"properties":{"provider":{"$ref":"#/components/schemas/ProviderSelection"},"model":{"type":"string","example":"google/gemini-3.8-flash-tts","description":"An available model with kind tts from GET /v1/models. Inspect its tts metadata and capabilities; the example ID is illustrative."},"input":{"type":"string","description":"Plain text; model input limit is in UTF-8 bytes."},"voice":{"type":"string","example":"Kore"},"language":{"type":"string","description":"Select from the model’s tts.languages list. Use auto only when tts.auto_language is true; defaults depend on the model."},"style":{"type":"string","description":"Separate delivery instructions where supported, at most 2000 UTF-8 bytes."},"max_output_tokens":{"type":"integer","minimum":1,"description":"Audio-token ceiling, bounded by the selected model. Defaults to its maximum."},"response_format":{"type":"string","enum":["mp3","wav","opus"],"description":"Select from the model’s tts.formats list. Defaults depend on the model; set explicitly to match your output file."},"format":{"type":"string","description":"Legacy-only alias for response_format; conflicting values are rejected."},"speed":{"type":"number","enum":[1],"default":1}}}}}},"responses":{"200":{"description":"Generated audio. Provider TTS reports X-Usage-Input-Tokens, X-Usage-Output-Audio-Tokens, X-Audio-Duration-Seconds and X-Serving-Mode. X-Billing-Status is settled or pending; X-Credits-Charged is present only after settlement. X-Audio-Replay reports available or unavailable; X-Replayed: true identifies retained audio. Replayed charge headers describe the original charge, not a new debit. BYOK has no RelayOn inference debit. Legacy character-metered providers use X-Usage-Characters.","content":{"audio/mpeg":{"schema":{"type":"string","format":"binary"}},"audio/wav":{"schema":{"type":"string","format":"binary"}},"audio/ogg":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid request body or model selection"},"401":{"description":"Authentication required: auth_required"},"402":{"description":"Insufficient credits or model_not_priced"},"403":{"description":"Model, provider or request capability is blocked by API-key, account or workspace restrictions."},"404":{"description":"Model not found"},"409":{"description":"Idempotency conflict, request in progress, uncertain prior submission or previously failed request. No additional synthesis is performed."},"410":{"description":"Completed audio was not retained, expired or was deleted. No new generation or charge."},"413":{"description":"Input exceeds the selected model byte limit."},"422":{"description":"Missing or rejected provider credentials, or unsupported synthesis options."},"429":{"description":"RelayOn request limit exceeded"},"500":{"description":"RelayOn internal_error; provider details are masked"},"502":{"description":"Connection to the generation service failed (upstream_connection_error)"},"503":{"description":"No model capacity (no_capacity), temporarily unavailable capacity (state_unavailable), or unavailable generation service (upstream_unavailable); honor Retry-After","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before retrying"}}},"504":{"description":"Generation service deadline exceeded (upstream_timeout)"}}}},"/v1/audio/speech/requests/{id}":{"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Read a speech receipt","tags":["TTS"],"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"description":"Speech receipt in the selected account or workspace. API keys can read only their own receipts. Personal account owners can read their account receipts. Organization owners and administrators can read receipts in the selected scope; other session members can read only their own. Returns measured usage, settlement state and audio availability without private source metadata. It never synthesizes audio.","responses":{"200":{"description":"Receipt status","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"model":{"type":"string"},"serving_mode":{"type":"string","enum":["byok","provided"]},"state":{"type":"string","enum":["admitted","submitting","received","settled","failed","uncertain"]},"created_at":{"type":"string","format":"date-time"},"duration_seconds":{"type":"number","nullable":true},"finish_reason":{"type":"string","nullable":true,"enum":["stop","length"]},"usage":{"type":"object","nullable":true,"properties":{"input_tokens":{"type":"integer"},"output_audio_tokens":{"type":"integer"}}},"charge_micro":{"type":"integer","nullable":true,"description":"Original settled charge in millionths of USD; null until settlement."},"audio":{"type":"object","properties":{"available":{"type":"boolean"},"expires_at":{"type":"string","format":"date-time","nullable":true}}}}}}}},"401":{"description":"Authentication required: auth_required"},"404":{"description":"Receipt not found in caller scope."}}}},"/v1/audio/speech/requests/{id}/audio":{"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Retrieve retained speech audio","tags":["TTS"],"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."},{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"description":"Same authorization as receipt status. Returns the original WAV while content policy permits. It may finalize pending settlement at original rates, but never synthesizes or creates another charge. X-Replayed is true; X-Credits-Charged describes the original charge. Available even while the original worker or provider is offline.","responses":{"200":{"description":"Retained audio","content":{"audio/wav":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Authentication required: auth_required"},"404":{"description":"Receipt not found in caller scope."},"409":{"description":"No completed result: in progress, failed or uncertain."},"410":{"description":"Audio not retained, expired or deleted."},"503":{"description":"Saved audio storage temporarily unavailable; retry this receipt without creating a new generation."}}}},"/v1/audio/transcriptions":{"post":{"summary":"Submit a recorded-audio transcription job","tags":["STT"],"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"description":"Asynchronous transcription. Both submission paths return HTTP 202 with a job ID and status, not the final transcript. Poll GET /v1/audio/transcriptions/jobs/{id}. STT normally progresses queued → processing → completed; OCR uses queued → running → succeeded. Keep polling queued, processing or uncertain; stop on completed, failed or cancelled. Do not resubmit an uncertain job. Unsupported language hints return HTTP 422 unsupported_language, with no automatic fallback to detection. Omit language for automatic detection when the selected model supports it. Published model rates apply; audio is validated before spend is reserved.","parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."},{"name":"Idempotency-Key","in":"header","schema":{"type":"string","maxLength":200},"description":"Scoped to the caller and account or workspace. Reuse returns the same job; conflicting input returns 409. Generated and echoed when omitted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SttRequest"}},"multipart/form-data":{"schema":{"type":"object","required":["model","file"],"additionalProperties":false,"properties":{"provider":{"type":"string","description":"JSON-encoded ProviderSelection object."},"model":{"type":"string","example":"relayon/stt"},"file":{"type":"string","format":"binary"},"language":{"type":"string","description":"A code from the selected model’s stt.languages list. Omit for automatic detection when stt.auto_language is true. Unsupported hints return 422 unsupported_language, without falling back to detection."},"timestamps":{"type":"string","enum":["none","word","segment"],"default":"none"},"diarize":{"type":"boolean","default":false},"channel_mode":{"type":"string","enum":["mixdown"]},"response_format":{"type":"string","enum":["json"]}}}}}},"responses":{"202":{"description":"Durable job accepted; poll its id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SttJob"}}}},"400":{"description":"Invalid request body or model selection"},"401":{"description":"Authentication required: auth_required"},"402":{"description":"Insufficient credits or model_not_priced"},"403":{"description":"Model, provider or request capability is blocked by API-key, account or workspace restrictions."},"404":{"description":"Model not found"},"409":{"description":"idempotency_conflict"},"413":{"description":"audio_too_large; maximum 1 GB"},"422":{"description":"invalid_audio, unsupported_format, unsupported_language, unsupported_option or audio_too_long"},"429":{"description":"RelayOn request limit exceeded"},"500":{"description":"RelayOn internal_error; provider details are masked"},"502":{"description":"Connection to the generation service failed (upstream_connection_error)"},"503":{"description":"No model capacity (no_capacity), temporarily unavailable capacity (state_unavailable), or unavailable generation service (upstream_unavailable); honor Retry-After","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before retrying"}}},"504":{"description":"Generation service deadline exceeded (upstream_timeout)"}}}},"/v1/audio/transcriptions/jobs":{"post":{"summary":"Submit a recorded-audio transcription job","tags":["STT"],"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"description":"Asynchronous transcription. Both submission paths return HTTP 202 with a job ID and status, not the final transcript. Poll GET /v1/audio/transcriptions/jobs/{id}. STT normally progresses queued → processing → completed; OCR uses queued → running → succeeded. Keep polling queued, processing or uncertain; stop on completed, failed or cancelled. Do not resubmit an uncertain job. Unsupported language hints return HTTP 422 unsupported_language, with no automatic fallback to detection. Omit language for automatic detection when the selected model supports it. Published model rates apply; audio is validated before spend is reserved.","parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."},{"name":"Idempotency-Key","in":"header","schema":{"type":"string","maxLength":200},"description":"Scoped to the caller and account or workspace. Reuse returns the same job; conflicting input returns 409. Generated and echoed when omitted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SttRequest"}},"multipart/form-data":{"schema":{"type":"object","required":["model","file"],"additionalProperties":false,"properties":{"provider":{"type":"string","description":"JSON-encoded ProviderSelection object."},"model":{"type":"string","example":"relayon/stt"},"file":{"type":"string","format":"binary"},"language":{"type":"string","description":"A code from the selected model’s stt.languages list. Omit for automatic detection when stt.auto_language is true. Unsupported hints return 422 unsupported_language, without falling back to detection."},"timestamps":{"type":"string","enum":["none","word","segment"],"default":"none"},"diarize":{"type":"boolean","default":false},"channel_mode":{"type":"string","enum":["mixdown"]},"response_format":{"type":"string","enum":["json"]}}}}}},"responses":{"202":{"description":"Durable job accepted; poll its id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SttJob"}}}},"400":{"description":"Invalid request body or model selection"},"401":{"description":"Authentication required: auth_required"},"402":{"description":"Insufficient credits or model_not_priced"},"403":{"description":"Model, provider or request capability is blocked by API-key, account or workspace restrictions."},"404":{"description":"Model not found"},"409":{"description":"idempotency_conflict"},"413":{"description":"audio_too_large; maximum 1 GB"},"422":{"description":"invalid_audio, unsupported_format, unsupported_language, unsupported_option or audio_too_long"},"429":{"description":"RelayOn request limit exceeded"},"500":{"description":"RelayOn internal_error; provider details are masked"},"502":{"description":"Connection to the generation service failed (upstream_connection_error)"},"503":{"description":"No model capacity (no_capacity), temporarily unavailable capacity (state_unavailable), or unavailable generation service (upstream_unavailable); honor Retry-After","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds before retrying"}}},"504":{"description":"Generation service deadline exceeded (upstream_timeout)"}}}},"/v1/audio/transcriptions/jobs/{id}":{"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Read a transcription job","tags":["STT"],"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"description":"Only the creating caller in the same account or workspace can read this job. Terminal failures return HTTP 200 with status failed and a safe error. Uncertain jobs must be polled rather than resubmitted.","responses":{"200":{"description":"Job lifecycle and completed transcript","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SttJob"}}}},"401":{"description":"Authentication required: auth_required"},"404":{"description":"Job not found in caller scope"}}},"delete":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Request transcription cancellation","tags":["STT"],"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"description":"Best effort; does not promise upstream processing or billing stops. Cancelled gateway jobs have no customer charge.","responses":{"200":{"description":"Cancellation requested or existing terminal job","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SttJob"}}}},"401":{"description":"Authentication required: auth_required"},"404":{"description":"Job not found in caller scope"}}}},"/v1/ocr":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"post":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Extract text from a document","description":"Reads a document as markdown. Accepts PDF, images (jpg, png, heic, webp, gif, avif, tiff) and office documents (pptx, docx, xlsx). Billed per page processed rather than per token.","tags":["OCR"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OcrRequest"}}}},"responses":{"200":{"description":"Extracted pages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OcrResponse"}}}},"202":{"description":"Accepted as a job, when async is true","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OcrJob"}}}},"400":{"description":"Carries a code: invalid_document or invalid_json"},"401":{"description":"Authentication required: auth_required"},"402":{"description":"Insufficient credits, or the model has no price on record"},"403":{"description":"Model, provider or request capability is blocked by API-key, account or workspace restrictions."},"404":{"description":"Model not found"},"413":{"description":"The document is over the size limit"},"422":{"description":"Encrypted PDF validation failure: encrypted_pdf. Upload an unencrypted PDF."},"429":{"description":"RelayOn request limit exceeded"},"500":{"description":"RelayOn error: no_text_extracted for unreadable documents, otherwise upstream_error"},"502":{"description":"Connection to the generation service failed (upstream_connection_error)"},"503":{"description":"OCR capacity is unavailable"},"504":{"description":"Generation service deadline exceeded (upstream_timeout)"}}}},"/v1/ocr/jobs/{id}":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Poll a document job","description":"A job moves through queued, running and then succeeded or failed. A succeeded job carries the same result body the synchronous call returns. A failed job returns HTTP 200 with error.message and error.code, including encrypted_pdf; failed jobs are not billed.","tags":["OCR"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The job","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OcrJob"}}}},"404":{"description":"No such job, or it belongs to another account"}}}},"/v1/files":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"post":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Upload a document or audio file","description":"Accepts a raw body, a multipart file part, or base64 in JSON. Returns an id to pass to OCR as document.file_id or STT as audio.file_id. Set purpose=audio for STT; uploads are validated for transcription when submitted. An upload is deleted after 24 hours.","tags":["Files"],"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."},{"name":"X-File-Purpose","in":"header","description":"For raw audio uploads, set this header to audio.","schema":{"type":"string","enum":["ocr","audio"],"default":"ocr"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"purpose":{"type":"string","enum":["ocr","audio"],"default":"ocr"}}}},"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"string","description":"Base64 encoded document or audio"},"purpose":{"type":"string","enum":["ocr","audio"],"default":"ocr"},"filename":{"type":"string"},"content_type":{"type":"string","default":"application/pdf"}}}}}},"responses":{"201":{"description":"Stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileObject"}}}},"413":{"description":"Over the upload size limit"},"503":{"description":"Uploads are not available on this deployment"}}},"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"List uploads","tags":["Files"],"responses":{"200":{"description":"Your uploads","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/FileObject"}}}}}}}}}},"/v1/files/{id}":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Fetch one upload","tags":["Files"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The upload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileObject"}}}},"404":{"description":"No such file, or it belongs to another account"}}},"delete":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Delete an upload","tags":["Files"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"},"404":{"description":"No such file, or it belongs to another account"}}}},"/v1/models":{"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"List Models","description":"Returns all available models across all providers, plus the caller's combos when authenticated.","tags":["Models"],"responses":{"200":{"description":"Model list","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/ModelObject"}}}}}}}}}},"/v1/combos":{"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"List Combos","description":"Returns the caller's model combos. Auth via session cookie or API key.","tags":["Combos"],"responses":{"200":{"description":"Combo list","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Combo"}}}}}}}}},"post":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Create Combo","description":"Creates a new ordered model combo owned by the caller.","tags":["Combos"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboCreateRequest"}}}},"responses":{"201":{"description":"Combo created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Combo"}}}},"400":{"description":"Invalid combo definition"}}}},"/v1/combos/{id}":{"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Get Combo","tags":["Combos"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Combo","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Combo"}}}},"404":{"description":"Combo not found"}}},"patch":{"summary":"Update Combo","tags":["Combos"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComboCreateRequest"}}}},"responses":{"200":{"description":"Combo updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Combo"}}}},"404":{"description":"Combo not found"}}},"delete":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Delete Combo","tags":["Combos"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Combo deleted"},"404":{"description":"Combo not found"}}}},"/v1/usage":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"List Usage","description":"Paginated usage history. Session sees the whole account; API key scopes to that key only. Filters: from, to, model, provider, status, api_key_id, limit, offset. History window max 90 days.","tags":["Usage"],"parameters":[{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"model","in":"query","schema":{"type":"string"}},{"name":"provider","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["success","partial","error","cache_hit","accepted"]}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":200}},{"name":"offset","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Usage list","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageRecord"}}}}}}}}}},"/v1/usage/summary":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Usage Summary","description":"Aggregated totals for a window, including average requests per minute (rpm), average tokens per minute (tpm), generation speed (tps), and p50/p95 latency. Aggregate window max 31 days.","tags":["Usage"],"parameters":[{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"model","in":"query","schema":{"type":"string"}},{"name":"provider","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}}}}},"/v1/usage/timeseries":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Usage Timeseries","description":"Bucketed timeseries for charts. Bucket sizes: 1m, 5m, 1h, 1d.","tags":["Usage"],"parameters":[{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"bucket","in":"query","schema":{"type":"string","enum":["1m","5m","1h","1d"]}}],"responses":{"200":{"description":"Series","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageTimeseriesPoint"}}}}}}}}}},"/v1/usage/breakdown":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."},{"name":"X-Account-ID","in":"header","schema":{"type":"string"},"description":"Session requests only: personal or an organization ID. Uses that account’s provider keys, balance and playground resources. Do not combine with X-Workspace-ID or Bearer API-key authentication."}],"get":{"security":[{"bearerAuth":[]},{"sessionAuth":[]}],"summary":"Usage Breakdown","description":"Group aggregates by model, provider, status, or api_key.","tags":["Usage"],"parameters":[{"name":"from","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"group_by","in":"query","schema":{"type":"string","enum":["model","provider","status","api_key"]}}],"responses":{"200":{"description":"Rows","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string"},"data":{"type":"array","items":{"$ref":"#/components/schemas/UsageBreakdownRow"}}}}}}}}}},"/api/controls/guardrails":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."}],"get":{"summary":"Read Account, Workspace and Effective Guardrails","tags":["Controls"],"security":[{"sessionAuth":[]}],"responses":{"200":{"description":"Account and workspace policies, plus effective policies. Every policy must pass; API-key restrictions also apply."},"401":{"description":"Owner session required"}}}},"/api/controls/guardrails/{scope}":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."}],"put":{"summary":"Replace Inference Guardrails","tags":["Controls"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"scope","in":"path","required":true,"schema":{"type":"string","enum":["account","workspace"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InferencePolicy"}}}},"responses":{"200":{"description":"Saved guardrails. Checked before cache and dispatch."},"400":{"description":"invalid_controls"},"403":{"description":"Archived workspace or organization; role does not allow changes"}}}},"/api/controls/routing":{"parameters":[{"name":"X-Workspace-ID","in":"header","schema":{"type":"string","format":"uuid"},"description":"Selected personal or organization workspace for sessions with access. Bearer keys use their bound workspace."}],"get":{"summary":"Read Workspace Routing Preferences","tags":["Controls"],"security":[{"sessionAuth":[]}],"responses":{"200":{"description":"BYOK autoroute ranking, preferred provider order and fallback setting."}}},"put":{"summary":"Replace Workspace Routing Preferences","tags":["Controls"],"security":[{"sessionAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoutingPreferences"}}}},"responses":{"200":{"description":"Saved preferences. Never permit paid fallback on ar/ routes."},"400":{"description":"invalid_controls"},"403":{"description":"Archived workspace or organization; role does not allow changes"}}}},"/api/workspaces":{"get":{"summary":"List Accessible Workspaces","tags":["Workspaces"],"security":[{"sessionAuth":[]}],"responses":{"200":{"description":"Personal and organization workspace metadata, including membership role and archived workspaces."},"401":{"description":"Account session required"}}},"post":{"summary":"Create Workspace","tags":["Workspaces"],"security":[{"sessionAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":80},"organizationId":{"type":"string","format":"uuid","description":"Optional organization; requires owner or admin membership."}}}}}},"responses":{"201":{"description":"Created workspace. Uses the existing account balance."},"400":{"description":"Invalid name"},"401":{"description":"Account session required"}}}},"/api/workspaces/{id}":{"patch":{"summary":"Rename, Archive or Restore Workspace","tags":["Workspaces"],"security":[{"sessionAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"isArchived":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Updated workspace. Archival blocks new work while retaining resources and history."},"400":{"description":"Invalid update or default workspace archival"},"404":{"description":"Workspace unavailable to session"}}}},"/api/workspaces/{id}/budget":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Read Workspace Spending Limit","tags":["Workspaces"],"security":[{"sessionAuth":[]}],"responses":{"200":{"description":"Workspace spending cap, settled spending, pending estimates, remaining allowance and next reset."},"404":{"description":"Workspace unavailable to session"}}},"put":{"summary":"Set Workspace Spending Limit","tags":["Workspaces"],"security":[{"sessionAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["limit_micro","reset"],"properties":{"limit_micro":{"type":["integer","null"],"minimum":0},"reset":{"type":"string","enum":["none","daily","weekly","monthly"]}}}}}},"responses":{"200":{"description":"Updated budget. Account and key caps also apply; BYOK and cache hits are free."},"400":{"description":"Invalid budget"},"403":{"description":"Archived workspace or organization; role does not allow changes"},"404":{"description":"Workspace unavailable to session"}}}},"/api/privacy":{"get":{"summary":"Read Content Privacy Settings","tags":["Privacy"],"security":[{"sessionAuth":[]}],"responses":{"200":{"description":"Account privacy settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivacySettings"}}}},"401":{"description":"Account session required"}}},"patch":{"summary":"Update Content Privacy Settings","tags":["Privacy"],"security":[{"sessionAuth":[]}],"description":"Disabling capture deletes existing bodies. Shorter retention applies immediately; raising it cannot extend existing requests. Request metadata and transactions are retained.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["log_content","retention_days"],"properties":{"log_content":{"type":"boolean"},"retention_days":{"type":"integer","minimum":1,"maximum":30}}}}}},"responses":{"200":{"description":"Updated settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivacySettings"}}}},"400":{"description":"Invalid settings"},"401":{"description":"Account session required"}}}},"/api/privacy/content":{"delete":{"summary":"Delete Stored Request Content","tags":["Privacy"],"security":[{"sessionAuth":[]}],"description":"Deletes only the session owner’s stored request/response bodies and blocks late writes. Future capture remains unchanged. Uploaded files, OCR results and saved conversations are separate.","responses":{"200":{"description":"Bodies removed","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"integer","description":"Number of request body rows cleared."}}}}}},"401":{"description":"Account session required"}}}},"/v1/usage/{id}":{"get":{"summary":"Get Usage Record","tags":["Usage"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Usage record with privacy-filtered content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageDetail"}}}},"404":{"description":"Usage record not found"}}}},"/health":{"get":{"summary":"Health Check","description":"Returns server status and uptime.","tags":["System"],"security":[],"responses":{"200":{"description":"OK"}}}}}}