API limits: plan gates and throttles
Which API endpoints depend on plan features and count limits, which named throttles apply with which values, and what the 402, 429 and 503 responses look like.
In plain language
The API sets limits on requests. The plan you booked decides whether an endpoint is open. It also sets how many assistants and sources you can create. Counters limit how often you can call an endpoint in a period of time. This page lists every limit. It says which answer comes when a request is refused. And it shows how to deal with it.
All documentation topics
The API limits requests in two ways: through the booked plan and through counters. The plan decides whether an endpoint is open at all and which count limits for assistants, knowledge sources, documents, chunks and seats are checked on creation. Counters limit how often an endpoint may be called within a time window. This page lists every gate with its endpoint, value and response. For an overview of plans and quota, see Plans and quotas.
Plan gate and plan limits
Endpoints bound to a plan feature, a yes/no limit of the plan or a count limit check the account's plan before doing anything. The rejection carries status 402, which sets it apart from a missing role (403): someone in the account can grant a role, whereas a missing feature or a higher limit only comes with another plan. A count limit is reached as soon as the stock equals the limit, so with a limit of 1 the second assistant fails.
| Status | error | Other fields | Meaning |
|---|---|---|---|
| 402 | plan_feature_missing | feature, plan, plan_name and available_in | The plan lacks the feature the endpoint needs, or a yes/no limit of the plan is set to no; feature then names that limit. |
| 402 | plan_limit_reached | limit, allowed, used, plan and plan_name | The count limit is reached; nothing is created. |
| 503 | plan_limit_unmeasured | limit and reason | The stock could not be counted; nothing is created. |
| 500 | plan_gate_misconfigured | kind, feature or limit | The endpoint is bound to the plan incorrectly. This is an error on our side. |
| 403 | no_tenant | - | The request belongs to no account. |
limit and feature name the limit or feature by the key used in the tables below. plan is the plan key (for example start, pro or custom) and plan_name its display name (Start, Pro and, for the Custom plan, Individuell). available_in lists the keys of the plans that include the feature. allowed is the limit and used the current stock. These responses carry no message field, not even from status 500 upward; what counts is error.
antwort-402.json json
{
"error": "plan_limit_reached",
"limit": "assistants",
"allowed": 1,
"used": 1,
"plan": "start",
"plan_name": "Start"
}In the app, plan_feature_missing shows “Your Start plan does not include this feature. See Billing for the overview.”, plan_limit_reached shows “The Start plan limit is reached: 1 of 1. See Billing for the overview.” and any other 402 shows “Your plan does not cover this. See Billing for the overview.” Your plan and your figures take the place of “Start” and the numbers. A 503 appears as “The service reported an error. Please try again later.”
Features by endpoint
Feature (feature) | Endpoints under /api/v1 | Included in |
|---|---|---|
tool_and_api_control | POST keys, POST webhooks, PUT webhooks/{id} and POST webhooks/{id}/test, every endpoint under integration/, plus tools of type http and of the types for connected systems | Custom |
conversation_analytics | analytics/* except analytics/subscription | Pro, Custom |
shop_integration | catalog/*, including catalog/shop, catalog/shop/test and catalog/shop/sync | Pro, Custom |
appointment_and_lead | records/appointments and records/carts, plus tools of type appointment | Pro, Custom |
conversation_export | GET conversations/export and GET conversations/{id}/export | Start, Pro, Custom |
For tools, the API checks the tool type on creation, on update and when the tool runs. Without the feature, a tool of that type is neither created nor changed; the response is the same 402 with plan_feature_missing. The types for connected systems are order_status, order_change, inventory_status, price_lookup, calendar_availability, calendar_booking, crm_lead, crm_activities, callback_note and ticket_create. Appointments and baskets check the feature only when a status is changed; without the feature their lists can still be read and single cases deleted. GET records counts every kind, and plan_locked lists the kinds whose status cannot be changed. conversation_export is a yes/no limit of the plan; if it is missing, the API also responds with 402 plan_feature_missing, with feature set to conversation_export. How the app displays locked areas is described under Plans and quotas.
Count limits by endpoint
Endpoint under /api/v1 | Limits checked (limit) |
|---|---|
POST assistants | assistants |
POST setup/runs/{id}/accept | assistants |
POST knowledge/sources | knowledge_sources, documents and chunks |
POST setup/runs | knowledge_sources, documents and chunks |
POST knowledge/sources/{id}/refresh | documents and chunks |
POST team/invitations | seats |
The limits apply per account. The API checks the existing stock before the endpoint creates anything; once a limit is reached, nothing new is created. Documents and chunks only come into being while a source is read in, so the check compares the stock before reading with the limit. Restoring a source does not check any count limit. For seats, members and open invitations count together. More on seats is in Team and roles.
The value of each limit per plan is listed in Plans and quotas. When a request is turned down, allowed carries your account's limit and used the current count.
Named throttles
Besides the plan, named throttles limit the number of calls. Each name has its own counters, so an exhausted name only blocks the endpoints that carry it. Values are per minute; where an hourly figure is also given, it counts separately, and the request is rejected as soon as either counter is exhausted. Exceeding a throttle returns 429, and the app shows “Too many attempts. Please wait a moment.” General information on status codes is in API basics.
Per user
These throttles count per signed-in user. Without a session, the origin of the request counts instead. Someone who belongs to several accounts uses the same counter in all of them; only dpa counts separately per account and user. password-change is one shared counter for three endpoints.
| Name | Per minute | Endpoints under /api/v1 |
|---|---|---|
knowledge-sources | 20 | POST knowledge/sources, refreshing, restoring and embedding a source, POST setup/runs |
knowledge-search | 60 | Knowledge search |
knowledge-ask | 30 | Asking the knowledge base |
knowledge-probes | 6 | Running probe questions |
knowledge-tune | 2 | Tuning based on the probe questions |
assistants | 30 | Creating and updating assistants, creating and restoring versions, POST assistants/{id}/key, starting an acceptance run, creating and updating check questions, creating and updating tools; deleting is not throttled |
conversations | 30 | Creating conversations, exporting all or one, rating, revealing plain text and fetching attachments; GET analytics/report |
conversation-send | 20 | POST conversations/{id}/send |
catalog | 20 | Creating, importing and changing products; saving, testing and syncing the shop connection |
privacy | 5 | Account data export, objection to subprocessors, retention and deletion request |
dpa | 10 | Data processing agreement endpoint |
key | 10 | POST keys, POST webhooks and POST webhooks/{id}/test |
confirmation | 3 | Resending the confirmation email |
invitations | 5 | POST team/invitations |
tenant-switch | 20 | Switching accounts |
password-change | 5 | Changing the password, removing the code method and removing security keys |
Per origin
These throttles apply to endpoints without a session and count per origin: per address for IPv4 and per /64 network for IPv6. An IPv4 address written in IPv6 notation (::ffff:) counts as an IPv4 address. Minute and hour counters run separately.
| Name | Per minute | Per hour | Endpoints under /api/v1 |
|---|---|---|---|
status | 30 | - | public/status, public/changelog, fetching a demo with GET public/demo/{id} and public/accessibility |
enquiry | 5 | - | public/enquiry |
demo | 2 | - | POST public/demo |
register | 5 | 20 | POST register |
password-forgot | - | 20 | POST password/forgot |
auth-token | 30 | - | Address confirmation with POST verify and POST password/reset |
invitation | 20 | - | GET invitation/{token} and POST invitation/accept |
cart-pickup | 60 | - | cart/pickup/{token} |
Per visitor
The widget endpoints under /api/v1/public/widget/{key} count per visitor, formed from the origin and the widget key together. Visitors with the same origin therefore share a counter only within the same widget key. The widget caps apply in addition.
| Name | Per minute | Endpoints under /api/v1/public/widget/{key} |
|---|---|---|
widget-send | 12 | POST send, confirming a tool call and uploading an attachment |
widget | 60 | all other endpoints, including fetching the settings |
API key caps
The endpoints under /api/v1/integration authenticate with the X-Api-Key header, see API integration. Two caps apply to them, both counted per key, so one runaway integration does not stop the account's other keys.
| Cap | Value | Window |
|---|---|---|
| Per minute | Requests per minute field when the key is created, 1 to 6000, 120 if not set | 60 seconds from the first counted call |
| Per day | The account's daily limit, default 2,000; a value of 0 means no daily cap | Calendar day in UTC; the counter restarts at 00:00 UTC, which is 1 a.m. in Germany, or 2 a.m. during summer time |
- Both caps are checked before either one counts, so a rejected request uses up nothing. Counting happens before the scope check, though: a request that fails only because of a missing scope still counts against both caps.
- A key reports its per-minute limit through
GET /api/v1/integration/statusin thelimit_per_minfield, see Integration endpoints. - An existing key cannot be changed. For a different per-minute value, create a new key and revoke the old one.
- An account can have up to 10 valid keys; revoked and expired keys do not count. One more returns 422 with
too_many_keysandlimit, and the app shows “The maximum number of simultaneous keys has been reached.” GET /api/v1/keysstates the limit inlimit_active. The Interfaces page shows the count under API keys, for example as “3 / 10”.
antwort-429.json json
{
"error": "too_many_requests",
"scope": "minute",
"limit": 120,
"retry_after": 42,
"limit_per_min": 120,
"wait": 42
}scope is minute or day, limit is the cap that was exceeded and limit_per_min is the key's per-minute value. retry_after and wait contain the same wait time in seconds as the Retry-After header. For the daily cap it runs until the end of the day in UTC, but at least 60 seconds.
Widget caps
Besides the named throttles, the widget has two caps of its own whose values belong to the account: one for calls and one for questions. Each cap counts on the visitor and, if the call belongs to a conversation, also on that chat window session. A call belongs to a conversation if the conversation ID is in the path or sent as conversation_id in the body. Either carrier can reject; counting only happens once neither has rejected.
| Cap | Endpoints | Per minute | Per day |
|---|---|---|---|
| Calls | Settings, start, history, rating, revocation, export and deletion, plus confirming, rejecting and reporting a tool call | The account's Requests per minute value | The account's daily limit, default 2,000 |
| Questions | POST send | Default 10 | Default 200 |
- The per-minute value for calls is the account's Requests per minute value. Switching to a plan sets it to that plan's value: 20 for Start, 60 for Pro, 120 for Custom. If the account is already on Custom, a value stored there stays in place.
- The daily limit for calls is the same value as the daily cap of the API keys. For questions, an account may have a value other than the default.
- Uploading and fetching attachments are not subject to these caps; only the named throttles apply there.
- The windows run from the first counted call: 60 seconds for the minute and 86,400 seconds for the day. The day here is not a calendar day.
- A cap below 1 counts as switched off.
- The rejection is 429 with
too_many_requests,limit_per_min,limit_per_dayandwait, plus theRetry-Afterheader. - How the chat window reacts is described under Widget delivery.
Monthly quota
Once the month's quota is used up, the assistant generates no more replies. How this shows depends on the endpoint. The quota itself is described in Plans and quotas.
From 80 % of the quota onwards, the assistant keeps answering in throttled form: a reply is capped at 300 units and runs at most one tool round. Once the quota is used up, the service turns the question down before any reply is generated.
| Endpoint | Response |
|---|---|
POST /api/v1/integration/chat | 429 with quota_exhausted, scope set to month, month, budget, used and retry_after, plus the Retry-After header. The wait time runs until the month changes, at least 60 seconds. |
| Widget and the test dialog in the app | An error event with code set to quota_exhausted, scope set to month and retry_after, followed by the assistant's stored fallback reply. |
| Acceptance run | 422 with quota_exhausted. The app reports “The quota for this month is used up. A run would book every line as not measurable.” See Test and acceptance. |
Other counters
Some endpoints also keep their own counters. Their rejections carry their own error codes.
Endpoint under /api/v1 | Limit | Counted per | Response |
|---|---|---|---|
POST login | 5 failed attempts per minute, 20 per hour | Email address and origin | 429 too_many_attempts with retry_in |
POST login | 30 failed attempts per minute, 300 per hour | Origin | 429 too_many_attempts with retry_in |
POST password/forgot | 3 requests per hour | Email address and origin | 429 too_many_attempts with retry_in |
POST password/forgot | 10 emails per hour | Email address | 200 with {"ok":true}; nothing is sent in that case |
POST catalog/shop/test | 3 tests per minute | Account | 429 too_many_tests with retry_after and the Retry-After header |
POST catalog/shop/sync | one sync per 900 seconds | Shop connection | 429 sync_too_soon with retry_after, connection and the Retry-After header |
POST public/demo | 3 existing demos created within 24 hours | IP address | 429 demo_ip_limit |
POST public/demo | free capacity for demos | - | 503 demo_capacity |
POST public/widget/{key}/send, POST integration/chat and POST conversations/{id}/send | questions per conversation, set by the operator individually for each account: 0 to 1,000, default 60; 0 means no maximum | Conversation | in the event stream, error with conversation_limit and limit, followed by a notice text and handoff |
Only failed attempts count at sign-in. A successful sign-in releases the counter for email address and origin, while the per-origin counter keeps running. retry_in gives the wait time in seconds; sign-in and the password request do not send a Retry-After header. The limit of 10 emails per address does not change the response, and the request ends with 200. If a sync for the account is already waiting or running, POST catalog/shop/sync skips the waiting period and responds with 202, with already_pending set to true.
Handling rejections
- Distinguish by status: 402 calls for another plan, 403 for another role, 429 for a pause and 503 with
plan_limit_unmeasuredfor a later attempt. - If the
Retry-Afterheader is present, wait at least that many seconds. Otherwise evaluateretry_after,waitorretry_in. - Do not retry a 402 in a loop. It only changes with another plan or a smaller stock, for example after deleting an assistant.
- Give each integration its own key. The per-minute and per-day caps count per key.
- A key's daily cap restarts at 00:00 UTC; the widget's daily cap restarts 86,400 seconds after the first counted call.
Frequent questions
Why does the API respond with 402 instead of 403?
402 means the plan does not cover the endpoint or a count limit is reached. 403 stands for a missing role. This tells you whether another plan or another role is needed.
Do several API keys of one account share a counter?
No. The per-minute and per-day caps count per key. The daily value comes from the account and is the same for every key, but each key is counted separately.
When does a key's daily cap restart?
At 00:00 UTC. The counter belongs to the calendar day in UTC and expires when that day ends.
Do the per-user throttles apply across several accounts?
Yes. They count per user, even if that user belongs to several accounts. Only dpa counts separately per account and user.
Does a rejected request count?
Not for the key and widget caps. Both check every counter first and only count when none of them has rejected.
Ask it yourself, Assistant of this website
Automated assistant