Keys and security
Rate limits
Each key may make 120 calls a minute. Past that, calls answer 429 with a Retry-After header that says how long to wait.
The limit
Each key may make 120 calls a minute. The minute is counted per key, not per person or per company, so two keys made by the same person each have their own 120.
Only calls with a valid key count. Somebody who knows part of your key but not its secret cannot use up your minute.
When you go over
The call that goes past the limit, and every call after it until the minute turns, answers 429 with the code api.rate_limited and a Retry-After header:
HTTP/1.1 429 Too Many Requests
Retry-After: 23
Content-Type: application/json
{
"code": "api.rate_limited",
"error": "This key made too many calls in one minute.",
"requestId": null,
"detail": "23 seconds"
}Retry-After is the number of seconds until the minute turns. Wait that long, then call again. Do not retry sooner: every early retry is refused the same way.
Handling it in code
import os
import time
import requests
KEY = os.environ["PANLYTICS_KEY"]
def call(url: str) -> dict:
for _ in range(3):
answer = requests.get(url, headers={"Authorization": f"Bearer {KEY}"}, timeout=30)
if answer.status_code != 429:
answer.raise_for_status()
return answer.json()
time.sleep(int(answer.headers.get("Retry-After", "60")))
raise RuntimeError("Still rate limited after three waits.")async function call(url: string): Promise<unknown> {
for (let i = 0; i < 3; i++) {
const answer = await fetch(url, { headers: { Authorization: `Bearer ${process.env.PANLYTICS_KEY}` } });
if (answer.status !== 429) {
if (!answer.ok) throw new Error(`${answer.status}: ${(await answer.json()).code}`);
return answer.json();
}
const wait = Number(answer.headers.get("Retry-After") ?? "60");
await new Promise((done) => setTimeout(done, wait * 1000));
}
throw new Error("Still rate limited after three waits.");
}Other limits
| Limit | Value |
|---|---|
| Calls per key | 120 a minute |
| Wrong keys from one address | 30 a minute, then 429 from that address |
| Chat runs | 30 an hour per person, the same as in the app, then 429 net.rate_limited |
| Live streams per key | 3 at once, then 429 net.rate_limited with Retry-After: 15 until one closes |
| AI sign-in links | 6 an hour per key maker, then 429 agent.links_limit with Retry-After |
Chat also spends the shop's daily AI budget: 2 euros a day per shop unless the CEO or a Manager changes it in the organisation's AI settings. When a shop's budget for the day is used up, chat answers 429 with the code api.ai_budget and a Retry-After header holding the seconds until midnight UTC, when the day turns.