Plain HTTP and fetch
The API is plain HTTPS with JSON, so any HTTP client works. Send Authorization: Bearer ftai_... and Content-Type: application/json.
Request
bash
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": "Hello!"}]}'js
const response = await fetch('https://api.freetheai.org/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.FTAI_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'fta/zai/glm-5.3',
messages: [{ role: 'user', content: 'Hello!' }],
}),
})
const data = await response.json()
if (!response.ok) {
throw new Error(`${response.status}: ${data.error?.message} ${response.headers.get('x-error-id') ?? ''}`)
}
console.log(data.choices[0].message.content)python
import os
import requests
response = requests.post(
"https://api.freetheai.org/v1/chat/completions",
headers={"Authorization": f"Bearer {os.environ['FTAI_KEY']}"},
json={"model": "fta/zai/glm-5.3", "messages": [{"role": "user", "content": "Hello!"}]},
timeout=120,
)
data = response.json()
if not response.ok:
raise RuntimeError(f"{response.status_code}: {data['error']['message']}")
print(data["choices"][0]["message"]["content"])Read a stream by hand
Streams are server-sent events: lines that start with data: , separated by blank lines, ending with data: [DONE]. A stream that breaks ends with an event: error line instead.
js
const response = await fetch('https://api.freetheai.org/v1/chat/completions', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.FTAI_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'fta/zai/glm-5.3',
stream: true,
messages: [{ role: 'user', content: 'Count to ten.' }],
}),
})
if (!response.ok || !response.body) throw new Error((await response.json()).error?.message)
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader()
let buffer = ''
for (;;) {
const { value, done } = await reader.read()
if (done) break
buffer += value
const events = buffer.split('\n\n')
buffer = events.pop() ?? ''
for (const event of events) {
const data = event.split('\n').find((line) => line.startsWith('data: '))?.slice(6)
if (!data || data === '[DONE]') continue
const json = JSON.parse(data)
if (json.error) throw new Error(json.error.message)
process.stdout.write(json.choices?.[0]?.delta?.content ?? '')
}
}python
import json
import os
import httpx
payload = {
"model": "fta/zai/glm-5.3",
"stream": True,
"messages": [{"role": "user", "content": "Count to ten."}],
}
headers = {"Authorization": f"Bearer {os.environ['FTAI_KEY']}"}
with httpx.stream("POST", "https://api.freetheai.org/v1/chat/completions",
json=payload, headers=headers, timeout=120) as response:
response.raise_for_status()
for line in response.iter_lines():
if not line.startswith("data: "):
continue
data = line[6:]
if data == "[DONE]":
break
chunk = json.loads(data)
if "error" in chunk:
raise RuntimeError(chunk["error"]["message"])
for choice in chunk.get("choices", []):
print(choice["delta"].get("content") or "", end="", flush=True)From a browser
Do not put your key in code that runs in a browser: anyone can read it there. Call FreeTheAI from your own server and stream the result to the page, as in the JavaScript SDK example. Requests relayed through a Cloudflare Worker are not accepted, so run the server code somewhere else.

