Skip to main content
Lesson 5 of 12 · Chat Completions: OpenAI Compatibility

OpenAI SDK with xAI base_url

Lesson 5 of 12 Updated November 3, 2026 Developer
On this page
  1. Using the OpenAI SDK to Access Grok
  2. Configuration
  3. Calls Identical to OpenAI
  4. Streaming with the OpenAI SDK
  5. JavaScript / TypeScript
  6. Switching Between Providers
  7. What Doesn’t Carry Over Between Providers
  8. Key Takeaways

Updated November 3, 2026. According to the xAI Chat Completions reference, compatibility with the OpenAI SDK isn’t “100%“—several parameters aren’t supported by reasoning models, are ignored by recent models, or aren’t supported by any model. Source: xAI, Chat Completions.

Using the OpenAI SDK to Access Grok

One of the major advantages of the xAI Chat Completions endpoint is its compatibility with the OpenAI SDK. You can use the openai package you already know, simply changing the base_url to point to xAI servers.

This approach is ideal if you’re migrating an existing application from OpenAI to Grok, or if you want to switch between providers with minimal changes.

Configuration

Installation is the same as for any project using the OpenAI SDK:

pip install openai

The only difference is client creation, where you specify the base URL and xAI API key:

from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("XAI_API_KEY"),
    base_url="https://api.x.ai/v1"
)

The two essential parameters are:

  • api_key: Your xAI API key (not an OpenAI key)
  • base_url: https://api.x.ai/v1—this redirects requests to xAI instead of OpenAI

Calls Identical to OpenAI

Once the client is configured, usage is the same as with the standard OpenAI SDK—except for parameters xAI doesn’t support, detailed below:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("XAI_API_KEY"),
    base_url="https://api.x.ai/v1"
)

response = client.chat.completions.create(
    model="grok-4.20-0309-reasoning",
    messages=[
        {"role": "system", "content": "You are a technical assistant."},
        {"role": "user", "content": "What is the difference between TCP and UDP?"}
    ],
    temperature=0.7,
    max_tokens=1000
)

print(response.choices[0].message.content)

The only visible difference is the model name: grok-4.20-0309-reasoning instead of gpt-5.6, for example.

Streaming with the OpenAI SDK

Streaming works exactly the same way:

stream = client.chat.completions.create(
    model="grok-4.20-0309-reasoning",
    messages=[
        {"role": "user", "content": "Explain the concept of microservices."}
    ],
    stream=True
)

for chunk in stream:
    content = chunk.choices[0].delta.content
    if content:
        print(content, end="", flush=True)

JavaScript / TypeScript

The OpenAI SDK for Node.js works the same way:

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.XAI_API_KEY,
  baseURL: "https://api.x.ai/v1",
});

const response = await client.chat.completions.create({
  model: "grok-4.20-0309-reasoning",
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "Hello, how are you?" },
  ],
});

console.log(response.choices[0].message.content);

Note that the property is baseURL (capital U) in JavaScript, whereas it’s base_url in Python.

Switching Between Providers

The main benefit of this approach is the ability to change providers with a single variable:

import os
from openai import OpenAI

provider = os.getenv("LLM_PROVIDER", "xai")

configs = {
    "xai": {
        "api_key": os.getenv("XAI_API_KEY"),
        "base_url": "https://api.x.ai/v1",
        "model": "grok-4.20-0309-reasoning"
    },
    "openai": {
        "api_key": os.getenv("OPENAI_API_KEY"),
        "base_url": "https://api.openai.com/v1",
        "model": "gpt-5.6"
    }
}

config = configs[provider]
client = OpenAI(api_key=config["api_key"], base_url=config["base_url"])

This multi-provider architecture is common in production applications that want to maintain flexibility.

What Doesn’t Carry Over Between Providers

Compatible doesn’t mean identical. The xAI endpoint reference flags several parameters that reasoning models don’t support—frequency_penalty, presence_penalty (like grok-3) and stop. logprobs and top_logprobs are ignored without error by grok-4.20 and newer models, and logit_bias isn’t supported. Code that sets these parameters for OpenAI will need to remove them for Grok. Silently ignored fields are the trickiest, since nothing signals that they have no effect. Hosted tools also differ between providers: OpenAI’s web search isn’t xAI’s. Finally, xAI now classifies Chat Completions as a legacy endpoint and recommends the Responses API (lessons 11 and 12).

Key Takeaways

  • The OpenAI SDK works with xAI by simply changing base_url to https://api.x.ai/v1
  • Methods and response formats are the same, but some parameters aren’t supported (frequency_penalty, presence_penalty, stop on reasoning models, logit_bias) or are ignored (logprobs from grok-4.20 onward)
  • Adapt the API key, model name, and unsupported parameters
  • This approach simplifies migration from OpenAI and allows switching between providers
  • Streaming and OpenAI SDK typing work; hosted tools are specific to each provider