{
  "openapi": "3.1.0",
  "info": {
    "title": "Zalmir API",
    "version": "1.0.0",
    "description": "OpenAI-compatible chat completions and authenticated model discovery for a configured Zalmir gateway. Availability depends on the configured gateway and its current registry state. Every gateway response carries `Cache-Control: no-store` and `Access-Control-Allow-Origin: *`; browser preflight (`OPTIONS`) needs no key and returns 204, or 405 if `Access-Control-Request-Method` is not the route's method. A path the gateway does not serve returns 404 with code `not_found_error`. Errors use the OpenAI shape `{\"error\": {message, type, param, code}}`; branch on the HTTP status first and treat an unknown `code` by its status.",
    "x-verification": "Successful chat responses are delivered only after the gateway verifies the selected route's signed response. This does not claim hardware attestation or end-to-end confidentiality.",
    "x-billing": "A hold is reserved on your balance before a chat request is forwarded. You are charged only after a verified answer has been delivered. A request that fails without a verified answer is not charged: its hold is released in full, or, if the gateway cannot confirm the release, the request is left for reconciliation (503 `reconciliation_required` with a `request_id`). Per-token prices are being finalized and are not part of this document."
  },
  "servers": [
    {
      "url": "https://{project_ref}.supabase.co/functions/v1/gateway/v1",
      "description": "Zalmir gateway edge-function base. Replace project_ref with the project reference supplied by Zalmir. Paths in this document are appended to this base, e.g. .../functions/v1/gateway/v1/chat/completions.",
      "variables": {
        "project_ref": {
          "default": "your-project-ref",
          "description": "Project reference supplied by Zalmir (placeholder; not a working host)."
        }
      }
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "paths": {
    "/chat/completions": {
      "post": {
        "operationId": "createChatCompletion",
        "summary": "Create a chat completion (OpenAI-compatible)",
        "description": "Accepts an ordinary compatible Chat Completions request. The gateway routes only to an admitted registry endpoint and verifies the response before delivery. Billing: see `info.x-billing`. A 200 body is sent without `Content-Length`; the gateway completes the body only after the charge is recorded. If it cannot record the charge, or the seller is quarantined during delivery, it ends the body with an error instead, and that request is not charged. Treat any incomplete body as a failed request and keep the `X-Request-Id`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatCompletionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verified completion. JSON by default. With `stream: true`, a buffered server-sent-event stream (`text/event-stream`): the seller is always called with `stream: false`, and the verified answer is then sent as (1) one chunk per choice with the whole message as `delta` (role, content, `tool_calls` with an added `index`, and the choice's other fields such as `logprobs`) and `finish_reason: null`, (2) one chunk with an empty `delta` and the `finish_reason`, (3) only if `stream_options.include_usage` is true, one chunk with `choices: []` and `usage`, then (4) `data: [DONE]`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "X-Zalmir-Model": {
                "$ref": "#/components/headers/XZalmirModel"
              },
              "X-Zalmir-Provider": {
                "$ref": "#/components/headers/XZalmirProvider"
              },
              "X-Zalmir-Verified": {
                "$ref": "#/components/headers/XZalmirVerified"
              },
              "X-Zalmir-Verification-Scope": {
                "$ref": "#/components/headers/XZalmirVerificationScope"
              },
              "X-Zalmir-Prompt-Privacy": {
                "$ref": "#/components/headers/XZalmirPromptPrivacy"
              },
              "X-Zalmir-Model-Proof": {
                "$ref": "#/components/headers/XZalmirModelProof"
              },
              "X-Zalmir-Content-Safety": {
                "$ref": "#/components/headers/XZalmirContentSafety"
              },
              "X-Zalmir-Tool-Execution": {
                "$ref": "#/components/headers/XZalmirToolExecution"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "`data: <chat.completion.chunk JSON>` events as described above, ending with `data: [DONE]`."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientCredits"
          },
          "404": {
            "$ref": "#/components/responses/ModelNotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "499": {
            "$ref": "#/components/responses/ClientCanceled"
          },
          "502": {
            "$ref": "#/components/responses/UpstreamFailure"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequirePrivacy"
          },
          {
            "$ref": "#/components/parameters/RequireModelProof"
          }
        ]
      }
    },
    "/models": {
      "get": {
        "operationId": "listGatewayModels",
        "summary": "List models available to an authenticated gateway key",
        "description": "Standard authenticated model discovery. The list reflects models admitted by the gateway's current registry, proof, session, and serving state; it is not the public catalog.",
        "responses": {
          "200": {
            "description": "Authenticated gateway model list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayModelList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayModelsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ModelsServiceUnavailable"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/RequirePrivacy"
          },
          {
            "$ref": "#/components/parameters/RequireModelProof"
          }
        ]
      }
    },
    "/models/{model}": {
      "get": {
        "operationId": "retrieveGatewayModel",
        "summary": "Retrieve an exact model available to an authenticated gateway key",
        "description": "Returns one model from the gateway's currently admitted serving candidates. An unknown, nonadmitted, or unavailable model is not returned. This is distinct from the public catalog and is not a confidentiality or runtime-attestation claim.",
        "parameters": [
          {
            "name": "model",
            "in": "path",
            "required": true,
            "description": "Exact admitted model ID. Slashes may be sent raw or percent-encoded; invalid percent-encoding returns 404 `model_not_found`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequirePrivacy"
          },
          {
            "$ref": "#/components/parameters/RequireModelProof"
          }
        ],
        "responses": {
          "200": {
            "description": "Authenticated exact gateway model record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayModel"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayModelsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/ModelNotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ModelsServiceUnavailable"
          }
        }
      }
    },
    "/requests/{request_id}/response": {
      "get": {
        "operationId": "getSavedResponse",
        "summary": "Fetch the saved answer of one of your charged requests",
        "description": "Returns the exact bytes the gateway delivered for a charged chat completion, with their original content type: the JSON completion, or the full `text/event-stream` payload (ending `data: [DONE]`) for `stream: true`. Use it when your connection dropped during delivery: the request was charged once either way, and its answer is kept until you delete it or your account is deleted. Answers are encrypted at rest and readable only with a key of the buyer who made the request. Never runs a model and never charges. An answer is saved only after the charge is confirmed, so a request whose charge is still being reconciled may have no saved answer.",
        "parameters": [
          {
            "name": "request_id",
            "in": "path",
            "required": true,
            "description": "The `X-Request-Id` of the original chat completion (lowercase UUID). Any other value returns the same 404 `not_found`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/RequirePrivacy"
          },
          {
            "$ref": "#/components/parameters/RequireModelProof"
          }
        ],
        "responses": {
          "200": {
            "description": "The saved answer, byte for byte as delivered.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "X-Zalmir-Verified": {
                "$ref": "#/components/headers/XZalmirVerified"
              },
              "X-Zalmir-Verification-Scope": {
                "$ref": "#/components/headers/XZalmirVerificationScope"
              },
              "X-Zalmir-Prompt-Privacy": {
                "$ref": "#/components/headers/XZalmirPromptPrivacy"
              },
              "X-Zalmir-Model-Proof": {
                "$ref": "#/components/headers/XZalmirModelProof"
              },
              "X-Zalmir-Content-Safety": {
                "$ref": "#/components/headers/XZalmirContentSafety"
              },
              "X-Zalmir-Tool-Execution": {
                "$ref": "#/components/headers/XZalmirToolExecution"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayModelsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Saved response not found (`code` `not_found`). One identical answer for another buyer's request, an unknown or malformed id, a refunded, unsaved or still-unsettled request, and a deleted, expired or account-closed answer: it never reveals whether a response exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "description": "The saved answer failed its integrity check and is not returned (`code` `response_unreadable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Saved responses are temporarily unavailable (`code` `response_store_unavailable`), or `authentication_unavailable`, `confidential_inference_unavailable`, `model_attestation_unavailable`. Safe to retry; nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteSavedResponse",
        "summary": "Delete the saved answer of one of your charged requests",
        "description": "Permanently deletes your saved answer for this request; it cannot be saved again later. Deleting never changes a charge or balance. A second delete, or a delete of anything you cannot read, returns the same 404 `not_found`.",
        "parameters": [
          {
            "name": "request_id",
            "in": "path",
            "required": true,
            "description": "The `X-Request-Id` of the original chat completion (lowercase UUID). Any other value returns the same 404 `not_found`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/RequirePrivacy"
          },
          {
            "$ref": "#/components/parameters/RequireModelProof"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "id",
                    "object",
                    "deleted"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "object": {
                      "const": "saved_response.deleted"
                    },
                    "deleted": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayModelsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Saved response not found (`code` `not_found`). One identical answer for another buyer's request, an unknown or malformed id, a refunded, unsaved or still-unsettled request, and a deleted, expired or account-closed answer: it never reveals whether a response exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Saved responses are temporarily unavailable (`code` `response_store_unavailable`), or `authentication_unavailable`, `confidential_inference_unavailable`, `model_attestation_unavailable`. Safe to retry; nothing is charged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/models": {
      "get": {
        "operationId": "listPublicCatalogModels",
        "summary": "List the public model catalog",
        "description": "Public configured catalog (no authentication). It reports configured endpoint count, public evidence freshness, and current routing state separately. A catalog entry is not a promise of gateway availability; when route status cannot be read, routable_now is null.",
        "servers": [
          {
            "url": "https://zalmir.ai",
            "description": "Website origin for the public catalog; availability is environment-dependent."
          }
        ],
        "security": [],
        "parameters": [
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "score",
                "newest",
                "name"
              ],
              "default": "score"
            },
            "description": "Catalog sort order; `score` is the default. `newest` orders by the most recent public probe time, not by model creation. Unknown values are not rejected and fall back to `score`."
          },
          {
            "name": "provider",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by provider prefix or catalog owner."
          },
          {
            "name": "verdict",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "faithful",
                "drifted",
                "quantized-or-substituted",
                "flagged"
              ]
            },
            "description": "Exact match on the latest public verdict. Values are not validated: a value outside this list returns an empty list, not 400."
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Substring search on model ID."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 500
            },
            "description": "Page size, 1-500. A non-integer or out-of-range value returns 400."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "maximum": 100000
            },
            "description": "Page offset, 0-100000. A non-integer or out-of-range value returns 400."
          }
        ],
        "responses": {
          "200": {
            "description": "Public catalog list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCatalogModelList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid public-catalog pagination.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCatalogError"
                }
              }
            }
          },
          "429": {
            "description": "Public-catalog rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCatalogError"
                }
              }
            }
          },
          "500": {
            "description": "Public-catalog lookup failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCatalogError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Buyer API key supplied by Zalmir, sent as `Authorization: Bearer <key>`. The Bearer scheme is case-insensitive and accepts one or more ASCII spaces before the key. Keys have the form `zmk_` followed by 32 characters from `A-Z a-z 0-9 _ -`; the key itself remains case-sensitive. A missing, malformed or unknown key returns 401 `invalid_api_key`."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid chat request. `code` is one of: `invalid_request` (body is not JSON, `model` is not a non-empty string, `messages` is not an array, a message `content` that is not a string, a list of `text` and `image_url` parts (an `image_url` part needs a non-empty `image_url.url`; images are forwarded, never fetched; audio and other part types are not supported), `null` or absent, `max_tokens`/`max_completion_tokens` is not an integer or null, `provider.require_parameters` is not a boolean, a malformed `Content-Length` header, or a body that could not be read in time); `invalid_assurance_requirement`; `invalid_idempotency_key`; `invalid_model_alias`; `unsupported_endpoint_override`; `invalid_routing` (unknown or invalid `provider` preference, model list or variant, or a route override the gateway does not accept); `unsupported_model_variant` (the `:online` variant); `idempotency_unsupported_for_fallback` (an `Idempotency-Key` on a request that could try more than one provider; set `provider.allow_fallbacks` to `false` or name one provider); `embeddings_unsupported` (no admitted provider serves embeddings); `byok_api_unsupported` (`provider.byok` is only available on chat completions; no paid fallback is attempted). Some of these carry `X-Should-Retry: false`.",
        "headers": {
          "X-Should-Retry": {
            "$ref": "#/components/headers/XShouldRetry"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, malformed or unknown buyer key, or a non-Bearer Authorization scheme (`code` `invalid_api_key`, `type` `authentication_error`). The Bearer scheme is case-insensitive and accepts one or more ASCII spaces before the case-sensitive key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "InsufficientCredits": {
        "description": "The ledger reported that your available balance cannot cover the request hold (`code` `insufficient_credits`, `type` `insufficient_quota`). Only that ledger answer produces 402; other accounting faults are 503 `accounting_unavailable`. The body carries a top-level `request_id`, also sent as `X-Request-Id`.",
        "headers": {
          "X-Should-Retry": {
            "$ref": "#/components/headers/XShouldRetry"
          },
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ModelNotFound": {
        "description": "No admitted endpoint is available for the requested model, or a `~zalmir/` alias matched no admitted model (`code` `model_not_found`). With routing preferences: `no_eligible_provider` (no provider matches the routing policy), `no_free_endpoints` (a `:free` model has no free endpoint), or `no_provider_for_parameters` (`provider.require_parameters` is `true` and no provider supports every requested parameter).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "The method is not supported for this gateway route (`code` `method_not_allowed`).",
        "headers": {
          "Allow": {
            "$ref": "#/components/headers/Allow"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "A gateway rate limit was exceeded (`code` `rate_limit_exceeded`, `type` `rate_limit_error`). Limits apply per API key, per buyer account and, where the deployment configures it, per client address; exact limits may change. `Retry-After` gives integer seconds before retrying. When the limiter cannot supply an exact delay, the gateway uses a conservative 60-second backoff; this is not a guarantee of admission after that delay. If the request used your own provider key (BYOK) and that provider rate-limited it, the error `code` is `byok_rate_limited`; the provider's own `Retry-After` is not passed on and the gateway sends 60 seconds instead. `Retry-After` never changes `X-Should-Retry`: when that header is `false` the exact request is still terminal.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ClientCanceled": {
        "description": "The request was canceled by the client before a verified response was delivered (`code` `request_canceled`). If a hold had been placed, the body has `state` `released` and `request_id`, or the request is reported as 503 `reconciliation_required`.",
        "headers": {
          "X-Should-Retry": {
            "$ref": "#/components/headers/XShouldRetry"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "A gateway dependency is temporarily unavailable. `code` is one of `authentication_unavailable`, `accounting_unavailable`, `trusted_usage_unavailable`, `capacity_unavailable`, `route_registry_unavailable`, `route_verification_unavailable`, `reconciliation_required`, `confidential_inference_unavailable`, `model_attestation_unavailable`. `reconciliation_required` carries top-level `state` `reconciliation_required` and `request_id`; do not infer a financial outcome from it, and it never carries `Retry-After`. `capacity_unavailable` means the selected model's capacity was full and the hold was released in full (nothing charged; body has `state` `released` and `request_id`). It carries `Retry-After: 2`; without an `Idempotency-Key` it carries `X-Should-Retry: true`, and with one it carries `X-Should-Retry: false` because the same key now answers 409 (retry with a new key). `capacity_unavailable` before any hold means no node serving the model is online right now: nothing was held or charged, the body has `request_id` but no `state`, and it carries `Retry-After: 2` and `X-Should-Retry: true` with or without an `Idempotency-Key`. With routing preferences, also: `routing_policy_unavailable` (the account's saved routing defaults could not be read; nothing was held), `routing_price_unavailable` (a `max_price` ceiling could not be enforced or the selected tariff exceeds it; any hold is released in full), and `free_serving_unavailable` (a `:free` endpoint was selected but free serving is not enabled). `GET /generation` answers `account_read_unavailable` when generation records cannot be read. Some of these carry `X-Should-Retry: false`.",
        "headers": {
          "X-Should-Retry": {
            "$ref": "#/components/headers/XShouldRetry"
          },
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          },
          "Retry-After": {
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Gateway-generated integer seconds, present only on `capacity_unavailable` (2) or, defensively, on any 503 marked `X-Should-Retry: true` (60 when no exact delay is known). Never an upstream provider value. Delay advice only; it never changes `X-Should-Retry`."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "GatewayModelsBadRequest": {
        "description": "An `X-Zalmir-Require-*` header has an unsupported value (`invalid_assurance_requirement`).",
        "headers": {
          "X-Should-Retry": {
            "$ref": "#/components/headers/XShouldRetry"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "IdempotencyConflict": {
        "description": "The `Idempotency-Key` was already used. `idempotency_conflict`: the key was used with a different request body. `idempotency_replay_unavailable`: this exact request was already claimed; the body has top-level `state` (`held`, `captured` or `released`) and `request_id` (also sent as `X-Request-Id`). No new inference is started. Exception: a `captured` request whose answer was saved is answered with that saved answer instead (200 with `X-Zalmir-Replayed: true` and the original content type); see `GET /requests/{request_id}/response`.",
        "headers": {
          "X-Should-Retry": {
            "$ref": "#/components/headers/XShouldRetry"
          },
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "The request body is larger than 2 MiB, by declared `Content-Length` or by counted bytes (`code` `request_too_large`).",
        "headers": {
          "X-Should-Retry": {
            "$ref": "#/components/headers/XShouldRetry"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UpstreamFailure": {
        "description": "No verified response was delivered and nothing is charged. This covers both integrity failures and availability failures (every candidate unreachable, timed out, or returning an invalid response), and confirmed capture failures followed by a confirmed release. `code` is one of `upstream_verification_failed`, `upstream_timeout`, `capture_failed`, `attested_transport_rejected`, `seller_quarantined`, `seller_quarantine_unavailable`. The body carries top-level `reason` (human-readable, may change), `state` `released` and `request_id`.",
        "headers": {
          "X-Should-Retry": {
            "$ref": "#/components/headers/XShouldRetry"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ModelsServiceUnavailable": {
        "description": "Model discovery is temporarily unavailable. `code` is one of `authentication_unavailable`, `route_registry_unavailable`, `route_verification_unavailable`, `confidential_inference_unavailable`, `model_attestation_unavailable`.",
        "headers": {
          "X-Should-Retry": {
            "$ref": "#/components/headers/XShouldRetry"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "message",
          "type",
          "param",
          "code"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "param": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always null today."
          },
          "code": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/Error"
          },
          "state": {
            "type": "string",
            "enum": [
              "held",
              "captured",
              "released",
              "reconciliation_required"
            ],
            "description": "Ledger state of the request this error refers to, when one exists. `held`/`captured` appear only on 409 `idempotency_replay_unavailable`."
          },
          "request_id": {
            "type": "string",
            "description": "Gateway request identifier, when a request record exists."
          },
          "reason": {
            "type": "string",
            "description": "Human-readable failure reason on 502 responses; wording may change."
          }
        },
        "additionalProperties": true
      },
      "ChatCompletionRequest": {
        "type": "object",
        "required": [
          "model",
          "messages"
        ],
        "properties": {
          "model": {
            "type": "string",
            "examples": [
              "Qwen/Qwen3.5-9B"
            ],
            "description": "Model ID returned by authenticated /models. Also accepts the aliases `~zalmir/coder`, `~zalmir/chat`, `~zalmir/cheap` and `~zalmir/vision` (task name case-insensitive), which pick an admitted model by keyword match on model IDs; the selection may change. The response `model` is the resolved model ID, not the alias. An unknown alias task returns 400 `invalid_model_alias`; an alias with no current match returns 404 `model_not_found`."
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatMessage"
            },
            "description": "Required array. Items are forwarded to the serving endpoint and not validated by the gateway."
          },
          "stream": {
            "type": "boolean",
            "default": false,
            "description": "When true, the verified answer is returned as a buffered SSE stream (see the 200 response)."
          },
          "stream_options": {
            "type": "object",
            "additionalProperties": true,
            "description": "Only `include_usage` is read: when true, the stream includes a final usage chunk. This object is not forwarded to the serving endpoint."
          },
          "temperature": {
            "type": "number"
          },
          "top_p": {
            "type": "number"
          },
          "n": {
            "type": "integer"
          },
          "stop": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "max_tokens": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Must be an integer or null; any other value returns 400 `invalid_request`."
          },
          "max_completion_tokens": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Must be an integer or null; any other value returns 400 `invalid_request`."
          },
          "presence_penalty": {
            "type": "number"
          },
          "frequency_penalty": {
            "type": "number"
          },
          "logit_bias": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "logprobs": {
            "type": "boolean",
            "description": "When true, an answer is delivered (and charged) only if every choice includes `logprobs`; an answer without them is rejected like any other invalid response."
          },
          "top_logprobs": {
            "type": "integer",
            "description": "Forwarded unchanged to the serving endpoint."
          },
          "user": {
            "type": "string"
          },
          "response_format": {
            "type": "object",
            "additionalProperties": true
          },
          "seed": {
            "type": "integer"
          },
          "tools": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatTool"
            }
          },
          "tool_choice": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "additionalProperties": true
              }
            ]
          },
          "parallel_tool_calls": {
            "type": "boolean"
          },
          "functions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatToolFunction"
            }
          },
          "function_call": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "additionalProperties": true
              }
            ]
          },
          "service_tier": {
            "type": "string"
          },
          "reasoning_effort": {
            "type": "string"
          },
          "modalities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "audio": {
            "type": "object",
            "additionalProperties": true
          },
          "prediction": {
            "type": "object",
            "additionalProperties": true
          },
          "store": {
            "type": "boolean"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "endpoint_url": {
            "type": "string",
            "description": "Not supported; do not send. Routing always uses the gateway's own registry. If the model has an admitted route the field is removed and never forwarded; if it has none the request fails with 400 `unsupported_endpoint_override` instead of 404."
          }
        },
        "additionalProperties": true,
        "description": "Fields other than `model`, `messages`, `stream`, `stream_options`, `max_tokens`, `max_completion_tokens`, `logprobs` and `endpoint_url` are forwarded unchanged to the serving endpoint; the gateway does not promise that a given endpoint honors them."
      },
      "ChatMessage": {
        "type": "object",
        "required": [
          "role"
        ],
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "system",
              "developer",
              "user",
              "assistant",
              "tool",
              "function"
            ]
          },
          "content": {
            "$ref": "#/components/schemas/ChatMessageContent"
          },
          "name": {
            "type": "string"
          },
          "tool_call_id": {
            "type": "string"
          },
          "tool_calls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatToolCall"
            }
          },
          "function_call": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ChatFunctionCall"
              },
              {
                "type": "null"
              }
            ]
          },
          "audio": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true
          },
          "refusal": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": true
      },
      "ChatMessageContent": {
        "oneOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatContentPart"
            }
          }
        ]
      },
      "ChatContentPart": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Provider-compatible content-part type."
          },
          "text": {
            "type": "string"
          },
          "image_url": {
            "type": "object",
            "additionalProperties": true
          },
          "input_audio": {
            "type": "object",
            "additionalProperties": true
          },
          "file": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "ChatTool": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "function",
              "custom"
            ]
          },
          "function": {
            "$ref": "#/components/schemas/ChatToolFunction"
          },
          "custom": {
            "$ref": "#/components/schemas/ChatToolCustom"
          }
        },
        "additionalProperties": true
      },
      "ChatToolFunction": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "parameters": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "ChatToolCustom": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "format": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "ChatToolCall": {
        "type": "object",
        "required": [
          "id",
          "type"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "function",
              "custom"
            ]
          },
          "function": {
            "$ref": "#/components/schemas/ChatFunctionCall"
          },
          "custom": {
            "$ref": "#/components/schemas/ChatCustomCall"
          }
        },
        "additionalProperties": true
      },
      "ChatFunctionCall": {
        "type": "object",
        "required": [
          "name",
          "arguments"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "arguments": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "ChatCustomCall": {
        "type": "object",
        "required": [
          "name",
          "input"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "input": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "ChatCompletionResponse": {
        "type": "object",
        "required": [
          "id",
          "object",
          "created",
          "model",
          "choices",
          "usage"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "const": "chat.completion"
          },
          "created": {
            "type": "integer"
          },
          "model": {
            "type": "string",
            "description": "The model that served the request (the resolved ID when an alias was sent)."
          },
          "system_fingerprint": {
            "type": [
              "string",
              "null"
            ]
          },
          "choices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatCompletionChoice"
            }
          },
          "usage": {
            "$ref": "#/components/schemas/ChatUsage"
          }
        },
        "additionalProperties": true
      },
      "ChatCompletionChoice": {
        "type": "object",
        "properties": {
          "index": {
            "type": "integer"
          },
          "message": {
            "$ref": "#/components/schemas/ChatResponseMessage"
          },
          "finish_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "logprobs": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "ChatResponseMessage": {
        "type": "object",
        "properties": {
          "role": {
            "const": "assistant"
          },
          "content": {
            "$ref": "#/components/schemas/ChatMessageContent"
          },
          "tool_calls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatToolCall"
            }
          },
          "function_call": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ChatFunctionCall"
              },
              {
                "type": "null"
              }
            ]
          },
          "audio": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true
          },
          "refusal": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "additionalProperties": true
      },
      "ChatUsage": {
        "type": "object",
        "required": [
          "prompt_tokens",
          "completion_tokens",
          "total_tokens"
        ],
        "properties": {
          "prompt_tokens": {
            "type": "integer"
          },
          "completion_tokens": {
            "type": "integer"
          },
          "total_tokens": {
            "type": "integer"
          }
        },
        "additionalProperties": true
      },
      "GatewayModel": {
        "type": "object",
        "required": [
          "id",
          "object",
          "created",
          "owned_by"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "const": "model"
          },
          "created": {
            "type": "integer",
            "description": "Unix seconds from the serving endpoint row's created_at, rounded down. Falls back to 0 when created_at is null, absent or invalid. When several endpoints serve a model, the first eligible route supplies this timestamp; it is not the model's training or release date."
          },
          "owned_by": {
            "type": "string",
            "const": "zalmir",
            "description": "Always zalmir. The gateway does not publish seller identities in model discovery."
          }
        },
        "additionalProperties": true
      },
      "GatewayModelList": {
        "type": "object",
        "required": [
          "object",
          "data"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GatewayModel"
            }
          }
        },
        "additionalProperties": true
      },
      "PublicCatalogModel": {
        "type": "object",
        "required": [
          "id",
          "object",
          "created",
          "configured_endpoints",
          "routable_endpoints",
          "routable_now",
          "verification"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "const": "model"
          },
          "created": {
            "type": "integer",
            "description": "Representative endpoint creation time as Unix seconds, or 0 when unavailable."
          },
          "owned_by": {
            "type": "string"
          },
          "tier": {
            "type": "string"
          },
          "configured_endpoints": {
            "type": "integer",
            "minimum": 1
          },
          "routable_endpoints": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Eligible endpoint count, or null when the private routing-status source is unavailable."
          },
          "routable_now": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "True when at least one endpoint has a current eligible route proof and a fresh serving node. Final admission happens at the gateway, which also applies seller and session checks, so a model shown here may still be absent from authenticated /models. Null means routing status is unavailable."
          },
          "buyer_price": {
            "type": "object",
            "description": "Exact buyer price from the approved tariff; absent when the model is not live.",
            "required": ["currency", "per_tokens", "prompt", "completion"],
            "properties": {
              "currency": {
                "type": "string",
                "enum": ["USD"]
              },
              "per_tokens": {
                "type": "string",
                "enum": ["1000000"]
              },
              "prompt": {
                "type": "string",
                "description": "Exact decimal string."
              },
              "completion": {
                "type": "string",
                "description": "Exact decimal string."
              }
            },
            "additionalProperties": false
          },
          "verification": {
            "type": "object",
            "required": [
              "status",
              "score",
              "verdict",
              "last_probed",
              "endpoint_counts"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "current_faithful",
                  "stale_faithful",
                  "flagged",
                  "unverified"
                ]
              },
              "score": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Catalog fidelity score when available."
              },
              "verdict": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "last_probed": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "endpoint_counts": {
                "type": "object",
                "required": [
                  "current_faithful",
                  "stale_faithful",
                  "flagged",
                  "unverified"
                ],
                "properties": {
                  "current_faithful": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "stale_faithful": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "flagged": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "unverified": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "additionalProperties": false
              }
            },
            "additionalProperties": true
          }
        },
        "additionalProperties": true
      },
      "PublicCatalogModelList": {
        "type": "object",
        "required": [
          "object",
          "routing_status",
          "data",
          "total_count",
          "links"
        ],
        "properties": {
          "object": {
            "const": "list"
          },
          "routing_status": {
            "type": "string",
            "enum": [
              "available",
              "unavailable"
            ]
          },
          "total_count": {
            "type": "integer"
          },
          "links": {
            "type": "object",
            "required": [
              "next"
            ],
            "properties": {
              "next": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "additionalProperties": true
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCatalogModel"
            }
          }
        },
        "additionalProperties": true
      },
      "PublicCatalogError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "additionalProperties": true
      }
    },
    "headers": {
      "XRequestId": {
        "schema": {
          "type": "string"
        },
        "description": "Gateway request identifier for reconciliation and support."
      },
      "RetryAfter": {
        "required": true,
        "schema": {
          "type": "integer",
          "minimum": 1
        },
        "description": "Seconds to wait before trying again (RFC 9110 Retry-After, delay-seconds only). Always generated by the gateway: the limiter's own delay when it supplies one, otherwise a conservative 60. An upstream provider's Retry-After is never relayed, including on a BYOK provider rate limit (`byok_rate_limited`), which also gets 60. This is delay advice only: it does not override `X-Should-Retry` and does not guarantee that the next request will be admitted."
      },
      "XShouldRetry": {
        "schema": {
          "type": "string",
          "enum": [
            "false",
            "true"
          ]
        },
        "description": "`false` on errors the gateway considers terminal for this exact request. `true` only on 503 `capacity_unavailable`, when nothing was reserved or charged: for a request sent without an `Idempotency-Key`, and for the no-node-online refusal (no `state`) with or without one. Its absence does not mean a retry is safe."
      },
      "Allow": {
        "schema": {
          "type": "string"
        },
        "description": "The single method this route accepts."
      },
      "XZalmirVerified": {
        "schema": {
          "const": "true"
        },
        "description": "The gateway verified the selected route's signed response before delivery."
      },
      "XZalmirVerificationScope": {
        "schema": {
          "const": "response-signature"
        },
        "description": "What was verified: the seller's response signature only."
      },
      "XZalmirPromptPrivacy": {
        "schema": {
          "const": "not-confidential"
        },
        "description": "The prompt was not processed under a confidentiality guarantee."
      },
      "XZalmirModelProof": {
        "schema": {
          "const": "not-attested"
        },
        "description": "The serving model and hardware were not attested."
      },
      "XZalmirContentSafety": {
        "schema": {
          "const": "not-certified"
        },
        "description": "No content-safety certification is made for the answer."
      },
      "XZalmirToolExecution": {
        "schema": {
          "const": "none"
        },
        "description": "The gateway never executes tools; tool calls are returned for your application to run."
      },
      "XZalmirModel": {
        "schema": {
          "type": "string"
        },
        "description": "Sent when the request was served through routing preferences (`zalmir/auto`, a `models` list or `provider` options): the exact Zalmir model ID that answered. Our canonical name, never the seller's claim."
      },
      "XZalmirProvider": {
        "schema": {
          "type": "string"
        },
        "description": "Sent with `X-Zalmir-Model`: the provider that answered, as named in the Zalmir catalog."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Optional exactly-once key for this chat request: 1-256 printable ASCII characters (0x21-0x7E), no spaces and no commas; anything else returns 400 `invalid_idempotency_key`. The key is bound to your account and the exact request body bytes. Reusing a key with the same body after it was claimed returns 409 `idempotency_replay_unavailable` with the original `request_id` and its `state` (`held`, `captured` or `released`); no new inference is started and the original answer is never returned. Reusing a key with a different body returns 409 `idempotency_conflict`. If the gateway cannot read the key's record it returns 503 `accounting_unavailable` rather than starting new work.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "pattern": "^[\\x21-\\x2B\\x2D-\\x7E]{1,256}$"
        }
      },
      "RequirePrivacy": {
        "name": "X-Zalmir-Require-Privacy",
        "in": "header",
        "required": false,
        "description": "Require confidential inference. The only accepted value is `confidential`; any other value returns 400 `invalid_assurance_requirement`. Confidential inference is not available today, so a valid value always fails closed with 503 `confidential_inference_unavailable` (it is never downgraded to ordinary serving).",
        "schema": {
          "type": "string",
          "enum": [
            "confidential"
          ]
        }
      },
      "RequireModelProof": {
        "name": "X-Zalmir-Require-Model-Proof",
        "in": "header",
        "required": false,
        "description": "Require attested model execution. The only accepted value is `attested`; any other value returns 400 `invalid_assurance_requirement`. Attestation is not available today, so a valid value always fails closed with 503 `model_attestation_unavailable`.",
        "schema": {
          "type": "string",
          "enum": [
            "attested"
          ]
        }
      }
    }
  }
}
