> ## Documentation Index
> Fetch the complete documentation index at: https://docs.square1.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Using OpenAI SDKs

> Point any OpenAI-compatible client at Square1

Square1 speaks the OpenAI wire format, so the official SDKs (and any tool
built on them) work with two settings:

* **Base URL** — `https://inference.square1.dev/v1`
* **API key** — your `sq-arca-...` key

## Setup

<CodeGroup>
  ```python Python theme={null}
  from openai import OpenAI

  client = OpenAI(
      base_url="https://inference.square1.dev/v1",
      api_key="sq-arca-...",
  )
  ```

  ```typescript Node.js theme={null}
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://inference.square1.dev/v1",
    apiKey: "sq-arca-...",
  });
  ```
</CodeGroup>

## Streaming

<CodeGroup>
  ```python Python theme={null}
  stream = client.chat.completions.create(
      model="deepseek-v4-pro",
      messages=[{"role": "user", "content": "Explain quicksort."}],
      stream=True,
  )
  for chunk in stream:
      delta = chunk.choices[0].delta
      if delta.content:
          print(delta.content, end="", flush=True)
  ```

  ```typescript Node.js theme={null}
  const stream = await client.chat.completions.create({
    model: "deepseek-v4-pro",
    messages: [{ role: "user", content: "Explain quicksort." }],
    stream: true,
  });
  for await (const chunk of stream) {
    process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
  }
  ```
</CodeGroup>

<Note>
  Reasoning models also emit a `delta.reasoning` channel the SDK types
  don't know about. It's carried in the raw chunk object — read it as an
  untyped field if you want to display thinking text, or ignore it.
</Note>

## Reasoning effort

On models with `supports_reasoning`, pass `reasoning_effort`. The Python
and Node SDKs both forward it natively:

```python theme={null}
completion = client.chat.completions.create(
    model="kimi-k2.6",
    reasoning_effort="high",
    messages=[{"role": "user", "content": "Prove it."}],
)
```

Allowed values are per-model. Sending a value the model doesn't accept
returns `400 invalid_reasoning_effort` with the allowed list in the
message.

## Tool calling

Models with `supports_tools` accept the standard `tools` /
`tool_choice` / `parallel_tool_calls` fields and answer with
`tool_calls` (ids always look like `call_<32 hex>`). Send tool results
back as `role: "tool"` messages, exactly as with OpenAI.

## What to expect that's different

* The response carries a [`wellspring` quota receipt](/concepts/quota-feedback) —
  SDKs preserve it as an extra field on the response object.
* Unsupported request fields (`n`, `presence_penalty`, `seed`,
  `response_format`, ...) are not part of the contract — don't rely on
  them.
* `max_tokens` is clamped to the model's `max_output_tokens`; input is
  capped by `max_input_tokens` (both visible in `GET /v1/models`).
* Errors follow the OpenAI envelope with Square1-specific codes — see
  [Errors](/concepts/errors), and note HTTP 529 (`model_overloaded`) is
  retryable.
