Limits
Several things bound a call. Some are yours, written in the policy document; the rest come from the app you are calling. All of them are refusals rather than errors: the call comes back as a normal answer with a code on it, nothing was half done, and the refusal is recorded like any other outcome.
| Limit | Code | Set by | When it fires |
|---|---|---|---|
| Velocity limit | velocity_exceeded | You, in the policy document | A token bucket you wrote is empty. Buckets are per project, per toolkit, or per tool, and every applicable one is tested before any token is spent. |
| Approval gate | approval_pending | You, in the policy document | The call matches a rule that says a person releases it. The call is parked, not failed. |
| Spend ceiling | budget_exhausted | You, in the policy document | The project or the entity has spent its budget for the current window. |
| Resource lease | resource_leased | atmon | Another caller holds the resource this tool declares, so two callers cannot write the same thing at once. |
| Provider budget | rate_limited | The external app | The provider's own declared request budget for this project and toolkit is spent. The table below lists the budgets that are declared. |
| Provider incident | provider_unavailable | The external app | The provider is in a known incident, so calls to it are refused rather than sent into a failure. |
What to do about each
| Code | What to do |
|---|---|
velocity_exceeded | Retry once the window refills. The detail names the wait in seconds. Nothing was sent and no credential was resolved. |
approval_pending | Retry with the approval_id once a person approves it in the console inbox. An approval that nobody answers expires rather than running late. |
budget_exhausted | The detail names the instant the window resets. Raise the ceiling or wait for it. |
resource_leased | Retry. The detail names the holder and when the lease expires. |
rate_limited | Retry after the wait the detail names. atmon never sleeps and never queues on your behalf, so your own timeout budget stays yours. |
provider_unavailable | Retry once the incident closes; the detail names it. |
Every code, including the ones that are not limits, is in Error codes.
Declared provider budgets
A toolkit may declare the request budget the external app publishes, and atmon paces against it with one bucket per project and toolkit. A connector that declares none is not unlimited: it is one where we have not written the number down, and a call that exceeds the provider's own limit comes back as rate_limited from the provider instead.
| Toolkit | Budget | Counted per |
|---|---|---|
| Airtable | 5 requests per 1s | account |
| Box | 1000 requests per 1m | account |
| ClickUp | 100 requests per 1m | account |
| GitHub | 5000 requests per 1h | account |
| GitLab | 2000 requests per 1m | account |
| Google Sheets | 60 requests per 1m | account |
| QuickBooks | 500 requests per 1m | account |
| Shopify | 40 requests per 20s | account |
| Slack | 50 requests per 1m | account |
| Stripe | 100 requests per 1s | account |
| Webflow | 60 requests per 1m | account |
| Xero | 60 requests per 1m | account |
Toolkits not listed here declare no budget. Every connector, listed or not, is in the app reference.
Sizes and shapes
Two limits are not refusals and are worth knowing before you meet them.
- A ranked slate from a search is at most eight tools. Asking for more returns eight.
- A tool result is shaped to the tool's output schema before you see it, so a provider answering with a large document does not arrive in your context whole.