Skip to content
View as Markdown

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.

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