Quickstart
Make your first request in a few minutes. You need a FreeTheAI account, an API key, and today's check-in; the code is the same OpenAI client code you already know, with a different base URL and key.
Get a key and check in
These steps happen on freetheai.org, by you:
- Create a free account and confirm your email.
- Open Dashboard > API keys and create a key. It starts with
ftai_, is 53 characters long, and is shown only once, so copy all of it. - Do today's check-in. Free models stay unlocked until 00:00 UTC.
Save the key in an environment variable
Keep the key out of your code. The examples on this site read it from FTAI_KEY.
export FTAI_KEY="ftai_your_key_here"$env:FTAI_KEY = "ftai_your_key_here"set FTAI_KEY=ftai_your_key_hereTo keep it across terminals, add the export line to your shell profile, or on Windows run setx FTAI_KEY "ftai_your_key_here" and open a new terminal.
Send your first request
Pick a language. Every example sends one message to fta/zai/glm-5.3 and prints the reply.
curl https://api.freetheai.org/v1/chat/completions \
-H "Authorization: Bearer $FTAI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "fta/zai/glm-5.3",
"messages": [
{"role": "user", "content": "Explain recursion in one paragraph."}
]
}'# pip install openai
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.freetheai.org/v1",
api_key=os.environ["FTAI_KEY"],
)
reply = client.chat.completions.create(
model="fta/zai/glm-5.3",
messages=[{"role": "user", "content": "Explain recursion in one paragraph."}],
)
print(reply.choices[0].message.content)// npm install openai (save as quickstart.mjs, run: node quickstart.mjs)
import OpenAI from 'openai'
const client = new OpenAI({
baseURL: 'https://api.freetheai.org/v1',
apiKey: process.env.FTAI_KEY,
})
const reply = await client.chat.completions.create({
model: 'fta/zai/glm-5.3',
messages: [{ role: 'user', content: 'Explain recursion in one paragraph.' }],
})
console.log(reply.choices[0].message.content)// npm install openai (run with: npx tsx quickstart.ts)
import OpenAI from 'openai'
import type { ChatCompletionMessageParam } from 'openai/resources/chat/completions'
const client = new OpenAI({
baseURL: 'https://api.freetheai.org/v1',
apiKey: process.env.FTAI_KEY ?? '',
})
const messages: ChatCompletionMessageParam[] = [
{ role: 'user', content: 'Explain recursion in one paragraph.' },
]
const reply = await client.chat.completions.create({
model: 'fta/zai/glm-5.3',
messages,
})
console.log(reply.choices[0].message.content ?? '')A successful reply looks like this (shortened):
{
"id": "chatcmpl-...",
"object": "chat.completion",
"model": "fta/zai/glm-5.3",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "Recursion is when a function solves a problem by calling itself..." },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 14, "completion_tokens": 96, "total_tokens": 110 }
}Stream the reply
For long replies, turn on streaming so words arrive as they are written. Very long replies without streaming can time out in some apps.
stream = client.chat.completions.create(
model="fta/zai/glm-5.3",
messages=[{"role": "user", "content": "Write a short story about a lighthouse."}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)const stream = await client.chat.completions.create({
model: 'fta/zai/glm-5.3',
messages: [{ role: 'user', content: 'Write a short story about a lighthouse.' }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? '')
}More on streaming.
If something goes wrong
| What you see | What to do |
|---|---|
401 unauthorized | The key is missing or incomplete. Paste the whole ftai_ key (53 characters). |
403 Daily check-in required | Do today's check-in, then send the request again. |
404 model not found | Copy an exact ID from freetheai.org/models, including the fta/ part. |
429 concurrency limit | A reply is still running. Free accounts run one request at a time. |
503 model busy | Retry in a minute or pick another model. Busy refusals do not count. |
Every message and its fix is on the errors page.
Next steps
- Want retries, fallback models, and typed errors built in? Use an official SDK for Python, JavaScript and TypeScript, or Go.
- Use a different model: Models and IDs.
- Give the model functions to call: Tool calls.
- Already using the Anthropic SDK or Claude Code? Point it at
https://api.freetheai.org: Anthropic SDK. - Set up an app instead of writing code: App guides.

