XuanShu API

OpenAI SDK migration conclusion

Migration requires changing the Base URL and API Key, then validating models, streaming, error retries, and rollback; it is not a 100% seamless replacement.

Last verified:

Connection and authentication

Unified OpenAI-compatible Base URL: https://www.xuanshuapi.com/v1

OpenAI-compatible APIs use Authorization: Bearer <YOUR_API_KEY>; Claude Messages also accepts x-api-key: <YOUR_API_KEY>; Gemini v1beta uses x-goog-api-key: <YOUR_API_KEY>.

export OPENAI_API_KEY="<YOUR_API_KEY>"
export OPENAI_BASE_URL="https://www.xuanshuapi.com/v1"

OpenAI SDK migration conclusion

XuanShu API provides OpenAI-compatible endpoints, but it is not a 100% seamless replacement: models, parameters, errors, and streaming events can differ, so validate gradually.

Not every model supports the same parameters; query Models first.

1. Save configuration and switch the Base URL and API Key

Keep the original configuration, then use separate XUANSHU_API_KEY and XUANSHU_MODEL variables for gradual validation.

export ORIGINAL_OPENAI_BASE_URL="${OPENAI_BASE_URL:-https://api.openai.com/v1}"
export ORIGINAL_OPENAI_API_KEY="<YOUR_ORIGINAL_KEY>"
export XUANSHU_API_KEY="<YOUR_API_KEY>"
export XUANSHU_MODEL="<MODEL_FROM_MODELS>"

2. Python initialization and real request

Install the openai package and run this minimal Chat Completions request.

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["XUANSHU_API_KEY"],
    base_url="https://www.xuanshuapi.com/v1",
)
response = client.chat.completions.create(
    model=os.environ["XUANSHU_MODEL"],
    messages=[{"role": "user", "content": "Reply with OK"}],
)
print(response.choices[0].message.content)

3. JavaScript initialization and real request

Install the openai package and run this ESM example.

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.XUANSHU_API_KEY,
  baseURL: "https://www.xuanshuapi.com/v1",
});
const response = await client.chat.completions.create({
  model: process.env.XUANSHU_MODEL,
  messages: [{ role: "user", content: "Reply with OK" }],
});
console.log(response.choices[0].message.content);

4. Discover and validate the model list

Query models visible to the current key, put a returned model ID in XUANSHU_MODEL, and then run the SDK examples.

curl https://www.xuanshuapi.com/v1/models \
  -H "Authorization: Bearer <YOUR_API_KEY>"

5. Validate streaming

Consume every chunk and handle empty deltas, timeouts, and interruption; confirm a non-streaming request first.

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.XUANSHU_API_KEY,
  baseURL: "https://www.xuanshuapi.com/v1",
});
const stream = await client.chat.completions.create({
  model: process.env.XUANSHU_MODEL,
  messages: [{ role: "user", content: "Count to three" }],
  stream: true,
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}

6. Handle errors with bounded retries

Do not automatically retry 401 or 403. Use bounded exponential backoff only for 429, timeouts, and recoverable 5xx responses.

import os
import random
import time
from openai import APIConnectionError, APIStatusError, APITimeoutError, OpenAI, RateLimitError

client = OpenAI(
    api_key=os.environ["XUANSHU_API_KEY"],
    base_url="https://www.xuanshuapi.com/v1",
    max_retries=0,
)

for attempt in range(4):
    try:
        response = client.chat.completions.create(
            model=os.environ["XUANSHU_MODEL"],
            messages=[{"role": "user", "content": "Reply with OK"}],
        )
        break
    except RateLimitError:
        if attempt == 3:
            raise
        time.sleep((2 ** attempt) + random.random())
    except (APITimeoutError, APIConnectionError):
        if attempt == 3:
            raise
        time.sleep((2 ** attempt) + random.random())
    except APIStatusError as error:
        if error.status_code < 500 or attempt == 3:
            raise
        time.sleep((2 ** attempt) + random.random())

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

7. Rollback

Keep separate references to the official endpoint and original key; restore them after a failed validation and reconcile migration usage.

export ORIGINAL_OPENAI_BASE_URL="https://api.openai.com/v1"
export ORIGINAL_OPENAI_API_KEY="<YOUR_ORIGINAL_KEY>"

# Roll back
export OPENAI_BASE_URL="$ORIGINAL_OPENAI_BASE_URL"
export OPENAI_API_KEY="$ORIGINAL_OPENAI_API_KEY"
unset XUANSHU_API_KEY XUANSHU_MODEL