# Limits and rate limits
Your plan sets limits: calls per minute, how much a query may read, upload size, active API keys and more. Read them from code so requests are right the first time.
## Read your limits [#read-your-limits]
### In Python [#in-python]
```python title="limits.py"
from klarety import Nexus
with Nexus.connect() as nexus:
limits = nexus.limits()
print("Plan family:", limits.family)
for knob in limits.knobs:
value = knob.fixed if knob.fixed is not None else knob.default
print(f"{knob.name}: {value} {knob.unit or ''} ({knob.description})")
```
`nexus.limits()` returns a `Limits` object:
| Field | Meaning |
| --- | --- |
| `family` | Your plan's family. |
| `knobs` | Every limit, as a `Knob`. |
| `studio_sizes` | Each Studio size your plan offers, with `cores` and `memory_gb`. |
Find one limit by name with `limits.knob("api_key.max_active")`. It raises `KeyError` when there is no such limit.
### What a knob holds [#what-a-knob-holds]
| Field | Meaning |
| --- | --- |
| `name` | The limit's name. |
| `description` | What it limits, in words. |
| `kind`, `unit` | Its type and unit. |
| `fixed` | The value, when your plan fixes it. |
| `default`, `minimum`, `maximum` | The default and range, when a project may choose within it. |
| `choices` | The allowed values, for a limit that is a choice. |
| `settable_on_project` | Whether a project may set its own value. |
### Over HTTP [#over-http]
```bash
curl -s https://api.klarety.ai/v1/limits -H "Authorization: Bearer $TOKEN"
```
### In the app [#in-the-app]
Open to see your credits, spend and plan limits.
`limits()` describes your plan. The server still checks every request, so handle refusals anyway.
## Fixed limits [#fixed-limits]
These are the same on every plan:
| Limit | Value |
| --- | --- |
| Request body | 1 MiB. Larger data goes through an upload, not the request. |
| Upload link | Lasts one hour. |
| `max_rows` on a SQL statement | 1 to 10,000, and never more than your plan's page of rows. |
| SQL parameters | Up to 256 per statement. |
| Rows changed by one `edit_rows()` | Up to 500. |
| Statements in one batch job | 1 to 50. |
| Edges sent in one `assert_edges()` | Up to 1,000. |
## When you reach a limit [#when-you-reach-a-limit]
| What happens | Status | SDK exception | What to do |
| --- | --- | --- | --- |
| Too many calls per minute | `429` with `Retry-After` | `RateLimitedError` | The SDK waits and retries. Slow your loop down. |
| Every statement slot busy | `429` | `OverBudgetError` | The SDK waits and retries. Send it again later. |
| A query would read too much | `413` | `OverBudgetError` | Narrow it; check with `nexus.estimate()`. |
| Body over 1 MiB | `413` | `OverBudgetError` | Send less, or upload a file. |
| Out of credits | `402` | `InsufficientCreditsError` | Add credits. |
| Another plan limit | `403` or `422` | `RefusedError` | The error's `limit` field names it. |
A refusing limit is named in the error's `limit` field, so you can ask for it to be raised. See [Errors](/docs/developers/errors).
## Next steps [#next-steps]
- [Errors](/docs/developers/errors) for the full error format.
- [Run SQL](/docs/developers/sql) to estimate a query before you run it.
- [Authentication](/docs/developers/authentication) to manage active keys.