Rate Limits
Limits
| Limit | Scope | Window |
|---|---|---|
| 60 req / min | Per API key | Sliding 60s |
| 120 req / min | Per IP address per endpoint | Sliding 60s |
Both limits use a sliding window — not a fixed clock minute.
429 response
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json{ "detail": "Rate limit exceeded (60/min per key)" }Handling 429s
import httpx, time
def chat_with_retry(text, session_id, retries=3):
for attempt in range(retries):
r = httpx.post(
"https://api.personaliai.com/api/v1/chat",
headers={"Authorization": "Bearer chatty_sk_key"},
json={"text": text, "session_id": session_id},
)
if r.status_code == 429:
wait = int(r.headers.get("retry-after", 60)) * (2 ** attempt)
time.sleep(wait)
continue
r.raise_for_status()
return r.json()
raise RuntimeError("Max retries exceeded")async function chat(text, sessionId, retries = 3) {
for (let i = 0; i < retries; i++) {
const res = await fetch("https://api.personaliai.com/api/v1/chat", {
method: "POST",
headers: { Authorization: "Bearer chatty_sk_key", "Content-Type": "application/json" },
body: JSON.stringify({ text, session_id: sessionId }),
});
if (res.status === 429) {
const wait = parseInt(res.headers.get("retry-after") || "60") * 2 ** i;
await new Promise((r) => setTimeout(r, wait * 1000));
continue;
}
return res.json();
}
}Best practices
| Endpoint | Additional limit |
|---|---|
POST /api/v1/knowledge (url) | 1 crawl per call; takes 2–5s |
GET /api/v1/leads | Max 200 per page |
Widget (/api/widget/chat) | 30 msg/60s per visitor IP + bot |
The widget rate limit is separate from the API key limit and only applies to embedded chat, not to API key requests.