{"components":{"schemas":{"ChatCompletion":{"properties":{"choices":{"items":{"properties":{"finish_reason":{"type":"string"},"index":{"type":"integer"},"message":{"$ref":"#/components/schemas/ChatMessage"}},"type":"object"},"type":"array"},"created":{"format":"int64","type":"integer"},"galtops":{"description":"Galtops extension block. Present when an extension was used: web_search (used, results, degraded, available) and learning (used).","type":"object"},"galtops_queue_id":{"description":"Galtops extension: set only on a completion collected from GET /v1/chat/queue/{id}.","type":"string"},"id":{"type":"string"},"model":{"type":"string"},"object":{"example":"chat.completion","type":"string"},"usage":{"properties":{"completion_tokens":{"type":"integer"},"prompt_tokens":{"type":"integer"},"total_tokens":{"type":"integer"}},"type":"object"}},"type":"object"},"ChatCompletionRequest":{"properties":{"learning":{"default":false,"description":"Galtops extension: opt this turn into the seat/org learning cache (read and write). Off by default for machine callers so an editor plugin does not silently fill a shared pool. Pinned permanent context is applied regardless. Header X-Galtops-Learning does the same; the body wins.","type":"boolean"},"max_completion_tokens":{"description":"Alias of max_tokens; max_tokens wins when both are sent.","type":"integer"},"max_tokens":{"type":"integer"},"messages":{"items":{"$ref":"#/components/schemas/ChatMessage"},"type":"array"},"model":{"description":"An id from GET /v1/models, or a role alias this key is allowed.","type":"string"},"search":{"default":false,"description":"Galtops extension: opt this turn into web search (SearXNG). Default is model-only — no internet egress. 400 if the deployment has no search configured (GET /api/meta reports search_enabled). Header X-Galtops-Web-Search does the same; the body wins.","type":"boolean"},"stream":{"default":false,"type":"boolean"},"temperature":{"type":"number"},"tool_choice":{"description":"String or object, as OpenAI defines it."},"tools":{"items":{"type":"object"},"type":"array"},"web_search":{"description":"Galtops extension: alias of search.","type":"boolean"}},"required":["model","messages"],"type":"object"},"ChatMessage":{"properties":{"content":{"description":"A string, or an array of parts for vision and PDF input: {\"type\":\"text\"}, {\"type\":\"image_url\"} (data: URI or public https:// only), {\"type\":\"file\"} for a PDF. Images are resized and child-safety scanned before they reach a model.","oneOf":[{"type":"string"},{"items":{"type":"object"},"type":"array"}]},"name":{"type":"string"},"role":{"enum":["system","user","assistant","tool"],"type":"string"},"tool_call_id":{"type":"string"},"tool_calls":{"items":{"type":"object"},"type":"array"}},"required":["role"],"type":"object"},"ChatQueueStatus":{"description":"Galtops extension: a deferred turn that has not finished yet.","properties":{"created_at":{"format":"int64","type":"integer"},"id":{"type":"string"},"model":{"type":"string"},"queue_depth":{"description":"Turns queued ahead of this one for the tenant.","type":"integer"},"state":{"enum":["queued","running"],"type":"string"},"updated_at":{"format":"int64","type":"integer"}},"type":"object"},"ComfyCompose":{"description":"Comfy protocol (comfy-scoped key), like POST /comfy/prompt. Not a studio session route.","properties":{"checkpoint":{"type":"string"},"dry_run":{"type":"boolean"},"image":{"description":"Owned LoadImage basename for edit.","type":"string"},"intent":{"enum":["generate","edit"],"type":"string"},"prompt":{"type":"string"}},"type":"object"},"ComfyPrompt":{"description":"ComfyUI prompt body: a node graph plus optional extra_data.","properties":{"client_id":{"type":"string"},"extra_data":{"type":"object"},"prompt":{"type":"object"}},"type":"object"},"ComfyPromptAccepted":{"properties":{"number":{"type":"integer"},"prompt_id":{"type":"string"}},"type":"object"},"ComfyPromptStatus":{"description":"ComfyUI GET /prompt queue snapshot.","type":"object"},"Error":{"description":"The OpenAI error envelope. Editor plugins surface error.message verbatim, so it is written for a person to read.","properties":{"error":{"properties":{"message":{"type":"string"},"type":{"type":"string"}},"type":"object"}},"required":["error"],"type":"object"},"Job":{"properties":{"card":{"type":"string"},"id":{"type":"string"},"output_rel":{"type":"string"},"output_url":{"description":"GET /api/jobs/{id}/output on this host (still authenticated). /file is the same bytes.","type":"string"},"status":{"type":"string"}},"type":"object"},"JobCreate":{"properties":{"card":{"description":"Studio card id (generate_image, edit_photo, photo_border, generate_video, …). photo_border takes multipart image plus border_color / border_width / border_style and optional decorative_frame / frame_style. Same authenticated queue as other stills.","type":"string"},"prompt":{"description":"For make_meme, prompt-only is enough: the prompt is the picture description when scene is omitted.","type":"string"},"scene":{"description":"Optional picture description for make_meme when it differs from the caption.","type":"string"},"style":{"type":"string"}},"required":["card"],"type":"object"},"JobList":{"properties":{"jobs":{"items":{"$ref":"#/components/schemas/Job"},"type":"array"}},"type":"object"},"Model":{"properties":{"created":{"description":"Unix seconds, or 0 when the backend reports no timestamp (the common case).","format":"int64","type":"integer"},"id":{"type":"string"},"object":{"example":"model","type":"string"},"owned_by":{"type":"string"}},"type":"object"},"ModelList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Model"},"type":"array"},"object":{"example":"list","type":"string"}},"type":"object"},"WorkerPlacement":{"description":"Derived placement for this box. kind=home for docker/darwin-native/empty driver when license.region is home or empty; kind=unknown for kube stub and non-home license.region. gpus is the facts list, never a count.","properties":{"driver":{"enum":["docker","darwin-native"],"type":"string"},"gpus":{"items":{"properties":{"index":{"type":"integer"},"name":{"type":"string"},"vram_mib":{"type":"integer"}},"type":"object"},"type":"array"},"intern_urls":{"description":"Compose-network Comfy hops, not public ports.","items":{"type":"string"},"type":"array"},"kind":{"enum":["home","unknown"],"type":"string"}},"required":["kind","driver","gpus","intern_urls"],"type":"object"},"WorkerSettings":{"description":"Owner worker settings. placement is the typed home record; other fields are the existing slots/facts/comfy payload.","properties":{"placement":{"$ref":"#/components/schemas/WorkerPlacement"}},"required":["placement"],"type":"object"}},"securitySchemes":{"bearerAuth":{"description":"A chat-scoped API key: `Authorization: Bearer \u003ckey\u003e`. Session cookies never authenticate these routes.","scheme":"bearer","type":"http"}}},"info":{"description":"The OpenAI-compatible surface, for your own tools. Authenticate with a\nchat-scoped API key as `Authorization: Bearer \u003ckey\u003e`; session cookies are\nignored on these routes on purpose.\n\nThis document describes only what is implemented. Stock OpenAI routes that\nthis deployment does NOT serve are absent by design and answer 404 in the\nOpenAI error envelope: `POST /v1/completions` (use chat completions),\n`POST /v1/responses` (use chat completions), `/v1/embeddings` (not a\nproduct API; do not implement embeddings), and the `/v1/images/*` family\n(image generation is POST /api/jobs or POST /comfy/prompt).\n\nNamed packs (stills, video, chat, meme) have feature parity across the\nconsumer UI, this authenticated API, and furyowner/admin\nGET/PUT /api/admin/capabilities. A pack that exists on one surface exists\non the others. GET /api/jobs/{id}/output is the advertised output_url;\nGET /api/jobs/{id}/file is the same bytes under the older name.\n\nThe stills pack is on (GET /api/meta capabilities.stills). POST /api/jobs with generate_image and POST /comfy/prompt answer 501 if an admin turns the pack off, or if this is a chat-only deployment.\nThe video pack is on (GET /api/meta capabilities.video). POST /api/jobs with generate_video answers 501 if an admin turns the pack off.\nThe chat pack is on (GET /api/meta capabilities.chat). POST /v1/chat/completions and /api/chat/* answer 501 if an admin turns the pack off. A deployment with no LLM backend still answers 404.\nThe meme pack is on (GET /api/meta capabilities.meme). POST /api/jobs with make_meme answers 501 if an admin turns the pack off.\n\nGaltops extensions (`search`, `learning`, the `galtops.*` response object,\n`GET /v1/chat/queue/{id}`) are additions to the OpenAI shape. A strict\nclient may ignore them. Human documentation: /docs/v1.","title":"Galtops OpenAI-compatible API","version":"1.0.0"},"openapi":"3.0.3","paths":{"/api/admin/capabilities":{"get":{"description":"Session cookie. furyowner/admin on this Host. Implemented packs: stills, video, chat, meme — the same names GET /api/meta.capabilities and the consumer cards use. Default on.","operationId":"getCapabilities","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Current capability flags."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No session or API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Caller is not furyowner/admin on this Host."}},"summary":"Read named instance capabilities","tags":["owner"]},"put":{"description":"Session cookie. Body: {\"stills\": false, \"video\": true, \"chat\": true, \"meme\": false}. Unknown names are refused. Default is on.","operationId":"putCapabilities","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Updated capability flags."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad JSON or unknown name."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No session or API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Caller is not furyowner/admin on this Host."}},"summary":"Turn named packs on or off","tags":["owner"]}},"/api/admin/workers":{"get":{"description":"Session cookie or API key. furyowner on this Host (same as /api/admin/tiers). Returns facts, suggestion, effective, owner_overwrite, setup_complete, and a typed placement record derived via placement.Derive (kind/driver from the live scaler or deps.runtime, gpus facts list, intern_urls). license.region other than home demotes kind to unknown; kube stays unknown. Placement is read-only; PUT and probe do not write it.","operationId":"getWorkerSettings","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerSettings"}}},"description":"Current worker settings."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No session or API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Caller is not furyowner on this Host."}},"summary":"Read stills/video/chat slot settings","tags":["owner"]},"put":{"description":"Session cookie or API key. Sparse overwrite of still/video/chat concurrency and model slots (0 is allowed). PUT {} or {\"reset\":true} clears workers.owner (reset to probe defaults).","operationId":"putWorkerSettings","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Updated worker settings."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad JSON."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No session or API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Caller is not furyowner on this Host."}},"summary":"Save a sparse owner overwrite","tags":["owner"]}},"/api/admin/workers/comfy":{"get":{"description":"Session cookie or API key. furyowner on this Host. Settings-backed instances beat env URLs; env is the fallback when settings are empty.","operationId":"getWorkerComfyInstances","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resolved Comfy instances."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No session or API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Caller is not furyowner on this Host."}},"summary":"Read resolved Comfy instance URLs","tags":["owner"]},"put":{"description":"Session cookie or API key. Body: {instances:[{url, roles?}]}. Empty list clears the settings row fallback to env. Adding a URL may need a process restart to spawn the hop.","operationId":"putWorkerComfyInstances","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Updated Comfy instances."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Bad JSON."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No session or API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Caller is not furyowner on this Host."}},"summary":"Save settings-backed Comfy instance URLs","tags":["owner"]}},"/api/admin/workers/probe":{"post":{"description":"Does not clear workers.owner. Session cookie or API key.","operationId":"probeWorkerSettings","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Updated worker settings after probe."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No session or API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Caller is not furyowner on this Host."}},"summary":"Re-probe hardware and refresh workers.slots","tags":["owner"]}},"/api/admin/workers/setup/complete":{"post":{"operationId":"completeWorkerSetup","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Updated worker settings."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No session or API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Caller is not furyowner on this Host."}},"summary":"Mark first-run worker setup complete","tags":["owner"]}},"/api/admin/workers/setup/reopen":{"post":{"operationId":"reopenWorkerSetup","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Updated worker settings."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No session or API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Caller is not furyowner on this Host."}},"summary":"Re-open first-run worker setup","tags":["owner"]}},"/api/comfy/compose":{"post":{"description":"Comfy protocol, like POST /comfy/prompt: comfy-scoped API key only. Session cookies and images keys use POST /api/jobs (the studio cards). The studio UI never calls this route. Builds an allowlisted txt2img or img2img graph and submits it on the same floors, ownership, and queue path as POST /comfy/prompt. Answers 501 when stills is off. A 401 without a comfy key is the protocol, not an unfinished UI.","operationId":"comfyCompose","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComfyCompose"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComfyPromptAccepted"}}},"description":"Accepted prompt, or the dry-run graph."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed spec or unsupported intent (analyze)."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key, or the key is not comfy-scoped."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unconfirmed email or a policy floor refused the prompt."},"501":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Image plane absent, or stills generation is off."}},"summary":"Build an allowlisted txt2img/img2img graph and submit it","tags":["comfy"]}},"/api/jobs":{"get":{"description":"Images-scoped API key or session cookie. Returns the caller's jobs.","operationId":"listJobs","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobList"}}},"description":"The job list."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key or session, or the key is unknown, revoked or expired."}},"summary":"List this account's studio jobs","tags":["jobs"]},"post":{"description":"Images-scoped API key or session cookie. Same cards the UI submits. Chat-only deployments answer 501. make_meme accepts prompt-only (no upload, no scene): the prompt is the picture description. An admin can turn stills off; generate_image then answers 501.","operationId":"createJob","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}},"description":"The queued job."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed body, unknown card, or missing input."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key or session, or the key is unknown, revoked or expired."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Wrong key scope, unconfirmed email, or a policy floor refused the prompt."},"501":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Chat-only (no image plane), or a named pack is off (generate_image / generate_video / make_meme). Bodies: stills generation / video generation / meme generation is not enabled on this deployment."}},"summary":"Submit a studio card (generate, edit, video)","tags":["jobs"]}},"/api/jobs/{id}":{"delete":{"operationId":"deleteJob","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Deleted."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key or session, or the key is unknown, revoked or expired."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such job for this account."}},"summary":"Delete one of this account's jobs","tags":["jobs"]},"get":{"operationId":"getJob","parameters":[{"description":"Job id returned by POST /api/jobs.","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}},"description":"The job, including output_url when finished."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key or session, or the key is unknown, revoked or expired."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such job for this account."}},"summary":"Poll one job","tags":["jobs"]}},"/api/jobs/{id}/cancel":{"post":{"operationId":"cancelJob","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}},"description":"The cancelled job."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key or session, or the key is unknown, revoked or expired."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such job for this account."}},"summary":"Cancel a queued or running job","tags":["jobs"]}},"/api/jobs/{id}/file":{"get":{"description":"Compatibility name for GET /api/jobs/{id}/output. Images-scoped API key or session cookie. Same ownership check as GET /api/jobs/{id}. Not a signed remote URL.","operationId":"getJobFile","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The image or clip bytes."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key or session, or the key is unknown, revoked or expired."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such job, or no file yet."}},"summary":"Download the finished bytes (alias of /output)","tags":["jobs"]}},"/api/jobs/{id}/output":{"get":{"description":"Advertised as output_url. Same ownership and bytes as GET /api/jobs/{id}/file. A 404 here while the studio preview works is a parity bug, not a documented exception.","operationId":"getJobOutput","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The image or clip bytes."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key or session, or the key is unknown, revoked or expired."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such job, or no file yet."}},"summary":"Download the finished bytes","tags":["jobs"]}},"/comfy/prompt":{"get":{"description":"Comfy-scoped API key. Same shape as ComfyUI GET /prompt.","operationId":"comfyPromptStatus","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComfyPromptStatus"}}},"description":"Queue status."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key, or the key is not comfy-scoped."}},"summary":"ComfyUI /prompt queue status","tags":["comfy"]},"post":{"description":"Comfy-scoped API key. Authenticated twin of ComfyUI POST /prompt. Also mounted at /comfy/api/prompt. Answers 501 when stills is off. Never point clients at the raw ComfyUI port.","operationId":"comfyPrompt","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComfyPrompt"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComfyPromptAccepted"}}},"description":"Accepted prompt."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed graph."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key, or the key is not comfy-scoped."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unconfirmed email or a policy floor refused the graph."},"501":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Image plane absent, or stills generation is off."}},"summary":"Submit a ComfyUI prompt graph","tags":["comfy"]}},"/v1/chat/completions":{"post":{"description":"With `stream: false` (the default) the response is one JSON object.\nWith `stream: true` the response is `text/event-stream`: a sequence of\n`data: {…}` chunks in OpenAI's `chat.completion.chunk` shape, ending with\n`data: [DONE]`. OpenAPI cannot describe an SSE frame sequence, so the\nstreaming response body is documented as a string.\n\nPolicy floors run on every user and tool message, and on search results\nand extracted PDF text, before inference.","operationId":"createChatCompletion","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletion"}},"text/event-stream":{"schema":{"description":"SSE frames of chat.completion.chunk objects, terminated by data: [DONE].","type":"string"}}},"description":"The completion, or an SSE stream when stream is true."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Malformed body, no model, no messages, a non-chat model, or search asked for where it is not configured."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key, or the key is unknown, revoked or expired."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The account's email address is not confirmed yet."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Chat is not configured, or the named model does not exist for this key."},"429":{"description":"Rate limited, or the turn was queued for capacity. When X-Galtops-Chat-Queued is present the turn WAS accepted and is running: poll GET /v1/chat/queue/{id} with that id. There is no SSE replay — this connection has already closed.","headers":{"Retry-After":{"description":"Seconds to wait before retrying or polling.","schema":{"type":"integer"}},"X-Galtops-Chat-Queue-Depth":{"description":"Turns queued ahead of this one for the tenant. Galtops extension.","schema":{"type":"integer"}},"X-Galtops-Chat-Queued":{"description":"Queue id to poll at GET /v1/chat/queue/{id}. Galtops extension.","schema":{"type":"string"}}}},"501":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Chat pack is off (capabilities.chat=false). Body: chat is not enabled on this deployment."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The inference backend failed or is not reachable."},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The organization's inference backend is not available."}},"summary":"Create a chat completion (blocking, or SSE with stream: true)","tags":["chat"]}},"/v1/chat/queue/{id}":{"get":{"description":"Not an OpenAI route. Use the id from the X-Galtops-Chat-Queued header of a\n429. While the turn is queued or running the body is a status object and\nRetry-After is set; once it is done the body is an ordinary\nchat.completion object with an extra galtops_queue_id field.","operationId":"getChatQueueItem","parameters":[{"description":"Value of the X-Galtops-Chat-Queued header.","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ChatQueueStatus"},{"$ref":"#/components/schemas/ChatCompletion"}]}}},"description":"Still queued or running (ChatQueueStatus), or finished (ChatCompletion).","headers":{"Retry-After":{"description":"Present while the turn is queued or running.","schema":{"type":"integer"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key, or the key is unknown, revoked or expired."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such queue item for this account."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The queued turn failed."}},"summary":"Poll a queued completion (Galtops extension)","tags":["chat"]}},"/v1/models":{"get":{"description":"Filtered per key: models the account's policy profile or the tenant's allow-list exclude are not listed. Answers 501 when the chat pack is off.","operationId":"listModels","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelList"}}},"description":"The model list."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key, or the key is unknown, revoked or expired."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Chat is not configured on this deployment (no LLM backend)."},"501":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Chat pack is off (capabilities.chat=false). Body: chat is not enabled on this deployment."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The inference backend is not reachable right now."},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The organization's inference backend is not available."}},"summary":"List the models this key may use","tags":["models"]}},"/v1/models/{id}":{"get":{"operationId":"getModel","parameters":[{"description":"Model id as returned by GET /v1/models.","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Model"}}},"description":"The model."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No API key, or the key is unknown, revoked or expired."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No such model, or this key may not use it."},"501":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Chat pack is off (capabilities.chat=false). Body: chat is not enabled on this deployment."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The inference backend is not reachable right now."},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The organization's inference backend is not available."}},"summary":"Describe one model","tags":["models"]}}},"security":[{"bearerAuth":[]}],"servers":[{"description":"This deployment","url":"https://mac.furybot.ai"}],"tags":[{"description":"Model catalogue visible to your key","name":"models"},{"description":"Chat completions and the queue extension","name":"chat"},{"description":"Studio cards: generate, edit, video (images-scoped key)","name":"jobs"},{"description":"Authenticated ComfyUI protocol (comfy-scoped key)","name":"comfy"},{"description":"Host-bound owner settings (session cookie or API key)","name":"owner"}]}
