Skip to content

OpenAI SDK compatibility

The official openai packages for Python and JavaScript, and any client that speaks the OpenAI HTTP API, work with two configuration changes:

client = OpenAI(base_url="https://api.siema-ai.pl/v1", api_key=os.environ["SIEMA_API_KEY"])

Nothing else in your code needs to change for chat completions or streaming, beyond setting model to a siema_ai alias. Embeddings need the same, plus one more thing: embed is a different model from whatever you used before, so its vectors aren’t compatible with ones you already stored (dimensions and semantics differ — OpenAI’s text-embedding-3-small, for example, returns 1536-dimensional vectors, embed returns 1024). Recompute anything you’ve already embedded after switching.

Endpoint Status
POST /v1/chat/completions Supported, streaming and non-streaming
POST /v1/embeddings Supported
GET /v1/models, GET /v1/models/{id} Supported, with siema_ai extensions
POST /v1/completions (legacy) Not offered
/v1/responses, /v1/files, /v1/images/*, /v1/audio/*, /v1/fine_tuning/*, /v1/batches, /v1/assistants Not offered

Calling an endpoint we do not offer, or a supported endpoint with the wrong HTTP method, returns 404 with error.code = "unsupported_endpoint" (calling one without an API key returns 401 first).

Field Behaviour
model Must be a siema_ai alias. Rewritten to the upstream model name internally; responses echo your alias.
max_tokens, max_completion_tokens Both are clamped to the model’s max_output_tokens and sent upstream as max_tokens. Omit either and the clamped ceiling is sent for you.
stream_options.include_usage Usage is always requested from the model server for billing; you receive the usage chunk only if you asked for it.
max_tokens, max_completion_tokens sent as JSON null Treated as absent, not forwarded as a literal null — the model’s ceiling is used. Every other field’s null is forwarded exactly as sent, with two exceptions: a null model or messages is 400 invalid_request rather than being forwarded, and a null stream_options on a streaming request is replaced with {"include_usage": true}.
OpenAI-Organization, OpenAI-Project and other client headers Not forwarded upstream; your API key alone identifies the organisation.
Everything else Forwarded unmodified.
  • Exhausted balance is HTTP 402, not 429. See Errors.
  • Error responses carry request_id, and X-Request-Id is always generated by siema_ai — a client-sent value is ignored, not echoed.
  • Model objects carry capabilities, context_length, max_output_tokens and pricing. Clients that validate model objects strictly against OpenAI’s schema should ignore unknown fields (the official SDKs do).
  • No X-RateLimit-* response headers; Retry-After is sent on 429.
  • n is forwarded with no limit applied; the model server may return more than one choice, and the output tokens of every choice returned are billed.
  • A mid-stream failure ends the connection with no in-band error event and no data: [DONE]; see Streaming for detection.
  • Embeddings encoding_format: base64 works — the official Python SDK requests it by default and decodes it for you; other clients may too. Both float and base64 work.
  • tools and tool_choice are forwarded to the model server unchanged, but tool calling isn’t guaranteed for every alias in V1; test with the alias you plan to use before relying on it. See Chat completions.
  • Model names such as gpt-4o return 404 model_not_found. Map them to polish-pro or advanced in your configuration.

Anything with an “OpenAI-compatible base URL” setting works: LangChain (ChatOpenAI(base_url=...)), LlamaIndex, Vercel AI SDK (createOpenAI({ baseURL })), LiteLLM (openai/polish-pro with api_base), Open WebUI, Continue, and most IDE assistants. Set the model name to an alias and the key to your sk-siema- key.

Two client-specific notes, as guidance rather than a promise:

  • LlamaIndex’s OpenAI class validates the model name against OpenAI’s own list and rejects an alias it doesn’t recognise; use OpenAILike instead.
  • LangChain’s OpenAIEmbeddings sends pre-tokenized integer arrays by default, which siema_ai’s embeddings endpoint rejects with 400 invalid_request (it only accepts strings). Pass check_embedding_ctx_length=False to send plain strings instead.