Buni.aiDocs

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, during the 7-day Pro trial, a monthly quota of runs and API calls.

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:

  1. The project's Rate limit / minute and Rate limit window (ms) in Settings › API Access › Advanced Settings.
  2. Your plan's API rate limit.
  3. The platform default of 120 per 60 seconds.

Responses from the bot and trigger endpoints carry these headers:

HeaderMeaning
X-RateLimit-LimitRequests allowed per window.
X-RateLimit-RemainingRequests left in the current window.
X-RateLimit-ResetUnix 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

The trial allows 200 runs and API calls per billing period. Pro and Business plans have no quota: each run and call uses a credit instead. The count is every run recorded for your organization since the period started, excluding dry runs, so automation runs started by a schedule, a webhook or another trigger count as well as API calls. 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": 200, "used": 200 }
}

That response also carries:

HeaderMeaning
X-Quota-LimitYour plan's limit for the period.
X-Quota-UsedCalls counted so far.
X-Quota-RemainingCalls left.
X-Quota-Period-StartStart 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.

When your credits are used up

When your organization's credits are used up and nothing pays for more (the trial, or a Pro or Business package without usage billing), every trigger and bot call returns 402, whatever the monthly quota says:

{
  "error": "This organization's credits are used up: chatbots, USSD, automations and API calls are paused until 3 Nov 2026.",
  "paused": { "until": "2026-11-03T00:00:00.000Z", "reason": "credits" }
}

Nothing runs and nothing is charged. Don't retry before paused.until. Dry runs ("dryRun": true) still work.

paused.reason says why: credits, trial_ended (below) or suspended (the organization is suspended; contact support). Only credits has a paused.until.

When the trial has ended

When a workspace's 7-day Pro trial has ended and no plan has been chosen, the workspace is read-only, through its API tokens as in the app. GET requests still work. Anything that runs or changes something returns 402:

{
  "error": "Your 7-day trial has ended, so this workspace is read-only. Choose a plan to keep building.",
  "trialEnded": true
}

Retrying won't help: choose a plan in Billing and Usage, and the same token works again.

Calls that don't use a token stop too: inbound webhooks, schedules and the bot channels. A trigger answers 402 with no date:

{
  "error": "This organization's trial has ended: chatbots, USSD, automations and API calls are paused until it chooses a plan.",
  "paused": { "until": null, "reason": "trial_ended" }
}

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.
Last reviewed 6 October 2026

On this page