Rate limits and quotas
How many API calls you can make per minute and per billing period, the headers that report them, and how to back off.
Two limits apply to the trigger and bot endpoints: a short-term rate limit per token, and a monthly quota of API calls from your plan.
Rate limit
Each token can call each endpoint a set number of times per window. The default is 120 requests per 60 seconds. Every endpoint has its own counter, so sync and async calls do not share one: 120 calls to /automations/.../trigger and 120 to /automations/.../trigger-async in the same minute are both allowed.
The limit is taken from, in order:
- The project's Rate limit / minute and Rate limit window (ms) in Settings › API Access › Advanced Settings.
- Your plan's API rate limit.
- The platform default of 120 per 60 seconds.
Responses from the bot and trigger endpoints carry these headers:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per window. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | Unix time, in seconds, when the window resets. |
Over the limit, the call returns 429 with {"error": "Rate limit exceeded"} and nothing runs. Wait until X-RateLimit-Reset, then retry.
Counts are kept per server instance, so treat the limit as approximate: plan for the documented number, and handle 429 whenever it comes.
The polling, dead-letter and invocation endpoints are not rate limited. Webhook trigger URLs have their own limit; see Inbound webhooks.
Monthly quota
Plans can cap the number of API calls per billing period. The count is every run recorded for your organization since the period started, excluding dry runs. The period starts on your subscription's renewal day, or on the first of the month (UTC) without an active subscription. Your plan's limit is shown in Billing and usage.
When the quota is used up, the call returns 429:
{
"error": "Monthly API call quota exceeded",
"quota": { "limit": 10000, "used": 10000 }
}That response also carries:
| Header | Meaning |
|---|---|
X-Quota-Limit | Your plan's limit for the period. |
X-Quota-Used | Calls counted so far. |
X-Quota-Remaining | Calls left. |
X-Quota-Period-Start | Start of the current period, ISO 8601. |
These headers are sent only on the quota-exceeded response, not on every call. If the quota cannot be checked at all, the call returns 503 {"error": "Unable to validate monthly API quota"}; retry after a short wait.
What does not count:
- Dry runs (
"dryRun": true). - Requests answered from an earlier run with the same idempotency key.
- Requests rejected before a run is created: bad token, wrong scope, rate limited.
Tell the two 429s apart
curl -i -X POST "https://www.buni.ai/api/v1/orgs/$ORG_ID/bots/$PROJECT_ID/message" \
-H "Authorization: Bearer $BUNI_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"message": "hi", "sessionId": "s-1"}'
# 429 with a "quota" object: monthly quota. 429 without it: rate limit.