Client SDKs
Use the official OpenAI, Anthropic and Google SDKs against LuluTokens — only the base URL changes.
There is no LuluTokens SDK, and you do not need one. The gateway speaks the same wire formats as OpenAI, Anthropic and Google, so the official SDKs work unchanged. You override two things: the base URL and the API key.
Read the key from the environment. An SDK client is easy to construct with a literal key, and that key then lives in your git history forever. Never ship one in browser or mobile code either — anything the client can read, a visitor can read.
OpenAI SDK
The default choice. Works for every model in the catalogue through
/v1/chat/completions.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["LULUTOKENS_API_KEY"],
base_url="https://api.lulutokens.ai/v1",
)
response = client.chat.completions.create(
model="kimi-k2.5",
messages=[{"role": "user", "content": "Say hello in one sentence."}],
)
print(response.choices[0].message.content)
print(response.usage)Streaming
Set stream: true. The stream ends with data: [DONE], exactly as with OpenAI.
stream = client.chat.completions.create(
model="kimi-k2.5",
messages=[{"role": "user", "content": "Count to five."}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)Anthropic SDK
For Claude models, if you would rather use the Anthropic wire format. Point
base_url at the host without /v1 — the SDK appends /v1/messages itself.
import os
from anthropic import Anthropic
client = Anthropic(
api_key=os.environ["LULUTOKENS_API_KEY"],
base_url="https://api.lulutokens.ai",
)
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=256,
messages=[{"role": "user", "content": "Say hello in one sentence."}],
)
print(message.content[0].text)The SDK sends the key as x-api-key, which the gateway accepts on /v1/messages
and /v1/models. You do not need to change anything for that to work.
OpenAI Responses API
What the Codex CLI uses. Same client, different method.
response = client.responses.create(
model="gpt-5.4",
input="Say hello in one sentence.",
)
print(response.output_text)Google GenAI SDK
For Gemini models through the native /v1beta surface.
import os
from google import genai
client = genai.Client(
api_key=os.environ["LULUTOKENS_API_KEY"],
http_options={"base_url": "https://api.lulutokens.ai"},
)
response = client.models.generate_content(
model="gemini-3-pro-image-preview",
contents="Say hello in one sentence.",
)
print(response.text)Some versions of this SDK put the key in the query string as ?key=... rather
than in the x-goog-api-key header. Both are accepted, but a key in a query
string is written to access logs in full where a header is not. Prefer a version
that sends the header, and treat a key that has been through a URL as exposed.
Frameworks
Anything that lets you set an OpenAI-compatible base URL works. There is nothing special to configure beyond these two values:
| Setting | Value |
|---|---|
| Base URL | https://api.lulutokens.ai/v1 |
| API key | your sk-... key |
That covers LangChain, LlamaIndex, Vercel AI SDK, Cline, Roo Code, Continue and
most others. Where a framework validates model IDs against its own hardcoded
list, use its "custom model" field and paste the exact ID from /v1/models —
our IDs will not be in anyone's built-in list.
Which model ID to use
Never hardcode an ID from an example, including the ones on this page. List what your key can actually reach:
curl https://api.lulutokens.ai/v1/models \
-H "Authorization: Bearer $LULUTOKENS_API_KEY"Passing an ID your key cannot reach returns 400. See
Models for the families available and
API reference for the full error table.