Skip to content
View as Markdown

OpenAI Python SDK

The official openai package works with FreeTheAI as is. Only the base URL and the key change.

Install and configure ​

bash
pip install openai
export FTAI_KEY="ftai_your_key_here"
python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.freetheai.org/v1",
    api_key=os.environ["FTAI_KEY"],
)

You can also set the environment variables the SDK reads by default, OPENAI_BASE_URL=https://api.freetheai.org/v1 and OPENAI_API_KEY=ftai_..., and create the client with OpenAI().

Chat completion ​

python
reply = client.chat.completions.create(
    model="fta/zai/glm-5.3",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Explain recursion in one paragraph."},
    ],
)
print(reply.choices[0].message.content)
print(reply.usage)

Streaming ​

python
stream = client.chat.completions.create(
    model="fta/kimi/k3",
    messages=[{"role": "user", "content": "Plan a three-step study schedule for Go."}],
    stream=True,
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Async ​

python
import asyncio
import os
from openai import AsyncOpenAI

client = AsyncOpenAI(base_url="https://api.freetheai.org/v1", api_key=os.environ["FTAI_KEY"])

async def main():
    reply = await client.chat.completions.create(
        model="fta/zai/glm-5.3",
        messages=[{"role": "user", "content": "Say hello in five words."}],
    )
    print(reply.choices[0].message.content)

asyncio.run(main())

Free accounts run one request at a time, so send requests one after another rather than with asyncio.gather.

Responses API ​

python
response = client.responses.create(
    model="fta/zai/glm-5.3",
    input="Write a haiku about the sea.",
)
print(response.output_text)

Tool calls ​

See Tool calls for a complete loop.

Fields the SDK does not know ​

Pass FreeTheAI-specific or model-specific fields with extra_body:

python
reply = client.chat.completions.create(
    model="fta/zai/glm-5.3",
    messages=[{"role": "user", "content": "Quick answer: 17 * 23?"}],
    extra_body={"thinking": {"type": "disabled"}},
)

Errors ​

The SDK raises typed exceptions. err.body holds FreeTheAI's error object, and its message is safe to show to people.

python
import openai

def error_message(err: openai.APIStatusError) -> str:
    body = err.body if isinstance(err.body, dict) else {}
    return body.get("message") or str(err)

try:
    reply = client.chat.completions.create(
        model="fta/zai/glm-5.3",
        messages=[{"role": "user", "content": "Hi"}],
    )
except openai.AuthenticationError as err:      # 401
    print("Check your key:", error_message(err))
except openai.PermissionDeniedError as err:    # 403, for example the daily check-in
    print("Not allowed:", error_message(err))
except openai.NotFoundError as err:            # 404, unknown model
    print("Unknown model:", error_message(err))
except openai.RateLimitError as err:           # 429
    print("Limit reached:", error_message(err))
except openai.APIStatusError as err:           # 400, 413, 502, 503, ...
    print(err.status_code, error_message(err), err.response.headers.get("x-error-id"))

The SDK retries some errors on its own (2 retries by default). Set max_retries and timeout on the client to change that. Every message and its fix: Errors.

FreeTheAI documentation. Paid models and plans are coming soon; the free tier has daily limits.