犀速AI
Contents
Updated 2026-10-16

Quickstart

Connect to the Xisu AI API in 5 minutes: Python, Node.js and curl

Sign up, add funds, create a key, set base_url, send your first request in Python, Node.js or curl, then check tokens and cost in Request log.

To use Xisu AI you need two things: an API key and a base_url. Any OpenAI-compatible SDK or tool works once you swap those two in — no other code changes.

Shortest path:

  1. Sign up and add funds (¥10 is a good start)
  2. Create a key under API keys in the console
  3. Set base_url to https://api.xisu.ai/v1
  4. Send your first request with any snippet below

Every snippet on this page was run against the live API with a real key (as of 2026-10-16). They all use gpt-6-luna, currently the lowest-priced model and a good fit for getting the pipeline working; to use another model, change model.

1. Sign up

Open the sign-up page, register with your email, and click the verification link in your inbox. If a new-user bonus is running, it lands in your balance once you verify (see the promotion page for terms). For a step-by-step with screenshots, see Sign up, add funds, create a key.

2. Add funds (start with ¥10)

Log in to the console, open Billing center in the left sidebar, choose ¥10.00 and click Top up now. Alipay and WeChat Pay are supported.

Billing top-up page

  • The console shows amounts in credits: ¥1 = 100,000 credits, so ¥10 is 1,000,000 credits.
  • Your balance does not expire. Each call is charged for what it actually used once it finishes; nothing is held in advance.
  • Prepaid only — once the balance reaches zero, new requests are refused. Refund rules: Top-ups and refunds.

3. Create an API key

Open API keys in the sidebar, give the key a name (for example "local test") and click Create key. Budget, IP allowlist and model allowlist can stay empty for now; see Key security and rotation when you need them.

Create an API key

The key is shown only once

The full key is shown exactly once. The server stores only a hash, so nobody can recover it after you close the page. Copy it right away; if you lose it, revoke it and create a new one.

To keep the key out of your code, every example below reads it from the XISU_API_KEY environment variable. Set it in the terminal where you run the code:

# Windows PowerShell
$env:XISU_API_KEY = "sk-your-key"
# macOS / Linux
export XISU_API_KEY="sk-your-key"

4. Set base_url

https://api.xisu.ai/v1

Keep the trailing /v1; without it you get 404 Not Found. The Anthropic SDK and Claude Code use the address without /v1 — see What is Xisu AI.

5. Send your first request

Python

pip install openai
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["XISU_API_KEY"],      # read from the environment; never hard-code keys
    base_url="https://api.xisu.ai/v1",
)

resp = client.chat.completions.create(
    model="gpt-6-luna",
    messages=[{"role": "user", "content": "Introduce yourself in one sentence"}],
)
print(resp.choices[0].message.content)
print(resp.usage)

The output looks like:

I’m ChatGPT, an AI assistant that helps answer questions, explain ideas, and create useful content.
CompletionUsage(completion_tokens=25, prompt_tokens=307, total_tokens=332, ...)

Node.js

Node.js 18+ has fetch built in, so no packages are needed. Save this as hello.mjs and run node hello.mjs:

const resp = await fetch("https://api.xisu.ai/v1/chat/completions", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${process.env.XISU_API_KEY}`,
  },
  body: JSON.stringify({
    model: "gpt-6-luna",
    messages: [{ role: "user", content: "Introduce yourself in one sentence" }],
  }),
});

const data = await resp.json();
if (!resp.ok) throw new Error(JSON.stringify(data.error));
console.log(data.choices[0].message.content);
console.log("x-request-id:", resp.headers.get("x-request-id"));
console.log("usage:", data.usage);

To use the official SDK instead, run npm i openai first:

import OpenAI from "openai";

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

const resp = await client.chat.completions.create({
  model: "gpt-6-luna",
  messages: [{ role: "user", content: "Introduce yourself in one sentence" }],
});
console.log(resp.choices[0].message.content);
console.log(resp.usage);

curl

macOS / Linux terminal (or Git Bash):

curl https://api.xisu.ai/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XISU_API_KEY" \
  -d '{"model":"gpt-6-luna","messages":[{"role":"user","content":"Hello"}]}'

In the returned JSON, choices[0].message.content is the reply and usage is the token count for this call.

Quoting JSON for curl in Windows PowerShell is error-prone, so use this instead (tested on the built-in Windows PowerShell 5.1):

$body = @{
  model    = "gpt-6-luna"
  messages = @(@{ role = "user"; content = "Introduce yourself in one sentence" })
} | ConvertTo-Json -Depth 5

$resp = Invoke-WebRequest -Uri "https://api.xisu.ai/v1/chat/completions" -Method Post -UseBasicParsing `
  -Headers @{ Authorization = "Bearer $env:XISU_API_KEY" } `
  -ContentType "application/json; charset=utf-8" `
  -Body ([Text.Encoding]::UTF8.GetBytes($body))

$data = [Text.Encoding]::UTF8.GetString($resp.RawContentStream.ToArray()) | ConvertFrom-Json
$data.choices[0].message.content
"x-request-id: " + $resp.Headers["x-request-id"]

Streaming

Add stream=True and the reply arrives piece by piece, which suits chat UIs that render as text is generated:

import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["XISU_API_KEY"], base_url="https://api.xisu.ai/v1")

stream = client.chat.completions.create(
    model="gpt-6-luna",
    messages=[{"role": "user", "content": "Write a three-line poem about autumn"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if chunk.usage:                       # last chunk: empty choices, usage only
        print("\n\nusage:", chunk.usage)

Streaming responses always end with an extra usage chunk whose choices array is empty. If you parse SSE yourself, don't assume every chunk has choices[0]; see API compatibility and parameters. If a stream is cut off midway, the tokens already generated are billed.

6. Find the call in Request log

After a successful call, open Request log in the console sidebar and you will see it. Each row shows:

Column Meaning
Time When the request happened
Request ID The request_id of this call
Model / key The model called and which key was used (prefix shown)
Tokens Broken down: input (of which cache hits), output (of which reasoning), cache writes, total
Duration How long the call took
Cost Credits charged for this call
Status Success / failed / client disconnected / upstream error / not billed

Request log list

You can filter by time range, key, status and request ID. Failed requests are listed too, with the cost shown as "0 credits, no output" — they are not charged. The page shows a "data as of" time; a call you just made may take a moment to appear.

7. Reconcile with x-request-id and usage

Every response carries an x-request-id header, and usage in the body holds that call's token counts. Log both and you can match any call against the console:

import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["XISU_API_KEY"], base_url="https://api.xisu.ai/v1")

raw = client.chat.completions.with_raw_response.create(
    model="gpt-6-luna",
    messages=[{"role": "user", "content": "1+1=?"}],
)
resp = raw.parse()
print("x-request-id:", raw.headers.get("x-request-id"))
print("prompt_tokens:", resp.usage.prompt_tokens)
print("completion_tokens:", resp.usage.completion_tokens)
print("total_tokens:", resp.usage.total_tokens)

The output looks like:

x-request-id: b694a772-4814-4f3e-973e-15537e7b023d
prompt_tokens: 306
completion_tokens: 5
total_tokens: 311

Reconciling takes three steps:

  1. In Request log, filter by Request ID using the x-request-id value to find the call.
  2. Check tokens: input and output in the console should match prompt_tokens and completion_tokens in usage; usage.prompt_tokens_details.cached_tokens is "of which cache hits" and usage.completion_tokens_details.reasoning_tokens is "of which reasoning".
  3. Check cost: the console's Input already includes incl. cache hits, so cost = (input − cache hits) × input price + cache hits × cache-read price + cache writes × cache-write price + output × output price. Prices are listed on the model catalog in credits per 1M tokens; reasoning tokens are charged at the output price. Divide credits by 100,000 to get yuan — 3,370 credits in the console is ¥0.0337.

One call filtered by request ID

For more, including why a cost can show as 0, see Reconciling usage and bills.

Common errors

What you see Cause Fix
401 invalid_api_key Wrong or revoked key, or your source IP is not on the key's allowlist Check the key in your environment variable; if the key has an IP allowlist, confirm your source IP
400 model_not_found Misspelled or retired model name Copy the exact name from the model catalog
404 Not Found base_url is missing /v1 Use https://api.xisu.ai/v1
insufficient_balance Not enough balance for this call Top up under Billing center. On the Anthropic-native endpoint, low balance is reported as 429 rate_limit_error

All error codes: Error codes and rate limits. When reporting a problem, include the x-request-id, the time, the model and the full error response.

Next steps