IsraelGPT API Docs Get an API key
The public API is offline until accounts come back. Existing API keys no longer work. The web chat at israelgpt.site works as usual. These docs describe the API as it was.

Examples

The basic request, plus a few common patterns: multi-turn context, picking a persona, handling media, and retrying safely.

Basic request

curl -X POST https://www.israelgpt.site/api/v1/chat \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{ "role": "user", "content": "What time is it in Tel Aviv?" }],
    "personaId": 1,
    "selectedModel": "israelbot-1",
    "effort": "low"
  }'

"Give to your AI agent" copies a full plain-text spec of this API (auth, parameters, response shape, errors) — paste it into Claude Code, Cursor, or any coding assistant and ask it to wire up the integration for you.

Multi-turn conversation

There's no server-side conversation memory for the API — you send the full history you want considered on every call, oldest message first. The reference Discord bot does this by reading the real last 10 Discord messages in a channel on every trigger (see Discord Bot).

{
  "messages": [
    { "role": "user", "content": "What's the capital of Israel?" },
    { "role": "assistant", "content": "Jerusalem, obviously..." },
    { "role": "user", "content": "And the largest city?" }
  ]
}

Picking a persona and model

See the full lists on Personas & Models. Example: the Tsundere persona (id 9) on IsraelBot 1, high effort:

{
  "messages": [{ "role": "user", "content": "Help me plan a trip to Eilat." }],
  "personaId": 9,
  "selectedModel": "israelbot-1",
  "effort": "high"
}

Uncensored mode

{
  "messages": [{ "role": "user", "content": "Roast my code review." }],
  "uncensoredMode": true
}

The Terms of Service's content and eligibility rules apply regardless of this flag — it changes language, not what's allowed.

Handling media in the response

If the persona's reply used an [IMAGE], [podcast], or [music] tag, media carries ready-to-use URLs — no need to parse the raw tags yourself:

const data = await res.json();

if (data.media?.images) {
  for (const img of data.media.images) {
    console.log("image:", img.url, img.tags);
  }
}
if (data.media?.podcast) {
  console.log("podcast (audio bytes at this URL):", data.media.podcast.url);
}

Retrying safely

A minimal retry loop that backs off on 429/502/503 and gives up on anything else (a 400/401 won't fix itself by retrying):

import httpx
import time

def ask(messages, max_attempts=3):
    for attempt in range(max_attempts):
        response = httpx.post(
            "https://www.israelgpt.site/api/v1/chat",
            headers={"Authorization": "Bearer YOUR_API_KEY"},
            json={"messages": messages},
            timeout=60,
        )
        if response.status_code == 200:
            return response.json()

        if response.status_code == 429:
            wait = response.json()["error"].get("retry_after_seconds", 5)
        elif response.status_code in (502, 503):
            wait = 2 ** attempt  # simple exponential backoff
        else:
            response.raise_for_status()  # 400/401 - won't fix itself, stop

        time.sleep(wait)

    raise RuntimeError("Gave up after retries")

Stripping bracket tags for a plain-text UI

If you're building something that only wants clean prose (no [ACTION:...]/[MEMORY:...]/etc. left visible), a simple regex strip works — this is exactly what the reference bot does:

import re

STRIP_TAG_RE = re.compile(
    r"\[(ACTION:[^\]]*|MEMORY:[^\]]*|flashcard:[^\]]*|QUESTION:[^\]]*|"
    r"get-time:[^\]]*|get-date:[^\]]*|create-file:[^\]]*|"
    r"LGBTQ_IMG|SEND_IDF|download|crisis-event[^\]]*)\]",
    re.IGNORECASE,
)

clean_text = STRIP_TAG_RE.sub("", data["reply"]).strip()