# Using the OpenAI SDK (/integrations/openai-sdk)



Zumik exposes an exact OpenAI-compatible surface at `https://api.zumik.ai/v1`. The fastest way onto the platform is no new dependency at all: keep your existing OpenAI client and change the base URL and the key. Your request and response handling, streaming, and tool calls all stay the same. This is the path the [OpenAI migration guide](/guides/openai-migration) walks through end to end.

## The base-URL swap [#the-base-url-swap]

The only line that changes is the base URL. Pass a Zumik [alias](/openai-compatibility) (`code.fast`, `auto.balanced`, `reasoning.best`, ...) as the `model`; Zumik resolves it server-side to a pinned provider release and reports the resolved release on the response headers, so a vanilla OpenAI SDK ignores the extra signal cleanly.

```bash
export ZUMIK_API_KEY="zk_..."
```

<CodeGroup>
  ```python title="Python"
  import os
  from openai import OpenAI

  client = OpenAI(
      base_url="https://api.zumik.ai/v1",   # the only change
      api_key=os.environ["ZUMIK_API_KEY"],
  )

  resp = client.chat.completions.create(
      model="code.fast",                    # a Zumik alias
      messages=[{"role": "user", "content": "Explain a rolling deploy."}],
  )
  print(resp.choices[0].message.content)
  ```

  ```typescript title="TypeScript"
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://api.zumik.ai/v1",     // the only change
    apiKey: process.env.ZUMIK_API_KEY,
  });

  const resp = await client.chat.completions.create({
    model: "code.fast",
    messages: [{ role: "user", content: "Explain a rolling deploy." }],
  });
  console.log(resp.choices[0].message.content);
  ```

  ```go title="Go"
  client := openai.NewClient(
      option.WithBaseURL("https://api.zumik.ai/v1"),   // the only change
      option.WithAPIKey(os.Getenv("ZUMIK_API_KEY")),
  )
  ```

  ```bash title="curl"
  curl https://api.zumik.ai/v1/chat/completions \
    -H "Authorization: Bearer $ZUMIK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "code.fast",
      "messages": [{"role": "user", "content": "Explain a rolling deploy."}]
    }'
  ```
</CodeGroup>

The official `openai-go` SDK takes the base URL via `option.WithBaseURL`. Streaming, function/tool calling, and structured output behave exactly as they do against OpenAI - that is the [compatibility contract](/openai-compatibility): no proprietary fields in the request or response body.

## Reuse stays measurable [#reuse-stays-measurable]

Proprietary outcomes ride on response headers so the JSON body stays byte-for-byte OpenAI's shape. Send `-i` (or inspect the response headers in your SDK) to see them:

```http
Agent-Execution-Profile: managed_provider
Agent-QoS-Target-Met: true
Agent-Trace-Id: trc_...
```

Where reuse savings apply, the discounted input fraction is also reflected in the standard `usage.prompt_tokens_details.cached_tokens` field, so [reuse](/concepts/reuse-metrics) stays measurable with a stock OpenAI SDK and nothing proprietary in the body.

## When to prefer this vs a native SDK [#when-to-prefer-this-vs-a-native-sdk]

<CardGroup cols="2">
  <Card title="Prefer the OpenAI SDK swap" icon="arrow-right-arrow-left">
    You have an existing OpenAI integration, you want streaming or the full chat/embeddings options today, or you just want generation against a Zumik alias with zero new dependencies.
  </Card>

  <Card title="Prefer a native Zumik SDK" icon="layer-group" href="/sdk/overview">
    You want explicit state - artifacts, bundles, sessions, branches, snapshots - plus diagnostics, token counts, and signed purge as first-class objects on `/v2`.
  </Card>
</CardGroup>

The two compose. A common shape is to build and pin state with a [Zumik SDK](/sdk/overview) on `/v2`, then run generation with the stock OpenAI client on `/v1`, attributing the request to the session with `Agent-*` headers. The [coding-agent example](/examples/coding-agent) does exactly this.

<Tip>
  Keep stable content (system instructions, tools, schema) at the front of the request so provider prompt caching can match the prefix. The [prompt linter](/tools/prompt-linter) checks the layout; [prompt layout](/guides/prompt-layout) explains the ordering.
</Tip>
