# 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.