# Limits and costs

> The limits the vault, the factory and the hosted app enforce, the deposit and gas of each call, and what a vault spends from its own NEAR.

Every cap, format, deposit and gas figure the vault, the factory, the console and the SDK use, read from the code. It also shows who pays each cost and what a vault spends from its own NEAR.

Status: Live · Network: Testnet · Reviewed: 2026-11-11 · Built from: 4ab41ca1436589c22073fa842ee46f970415e3d5

Canonical page: https://probarion.xyz/docs/build/limits-and-costs

Probarion's limits live in its code: the caps and formats the vault and the factory enforce, the deposit and gas of each call, what a vault spends from its own NEAR, and the hosted app's upload and rate limits. A test reads `contracts/vault/src`, `contracts/factory/src/lib.rs` and the TypeScript modules that define these values, and fails when a row on this page no longer matches them.

## How to read the tables

- **Constant** is the name in the source, such as `MAX_AGENTS` in `contracts/vault/src/lib.rs`. A Rust value is shown as the source computes it, and a TypeScript value comes from the module that exports it.
- **Units.** 1 NEAR is 10^24 yoctoNEAR, and 1 Tgas is 10^12 gas. Times on chain are in nanoseconds, as `block_timestamp` counts them, and times in TypeScript are in milliseconds. USDC amounts travel in base units, with 6 decimals.
- **Past the limit** and **Refused with** name the `PROBARION:<Code>` panic a call fails with, such as [`InvalidInput`](https://probarion.xyz/docs/build/errors.md#InvalidInput). A panic reverts every change the call made, and [Errors](https://probarion.xyz/docs/build/errors.md) explains each code.
- **Anchors.** Each row has its own anchor, such as [`limits-vault-max_agents`](#limits-vault-max_agents) or [`limits-deposit-create_mandate`](#limits-deposit-create_mandate).

## Vault limits

Every vault that runs the code in `contracts/vault/src` has these limits. No method changes the approvers, the allowed assets, the daily backstop or the hold time that `new` set, so a vault keeps them for life.

| Constant | Value | What it limits | Past the limit |
| - | - | - | - |
| `DAY_NS` | 86,400,000,000,000 ns (one day) | The day of the daily backstop: a spend counts in UTC day `block_timestamp / DAY_NS`, and the vault's `daily_backstop` caps each day's total | `OverDailyBackstop` |
| `MAX_HELD_TTL_NS` | 2,592,000,000,000,000 ns (30 days) | The `held_ttl_ns` of `new`: how long a held spend waits for an approver. It must also be above 0 | `InvalidInput`, and the vault is not created |
| `MAX_APPROVERS` | 10 | Approvers named in `new`, at least 1. No method changes them after the vault is created | `InvalidInput`, and the vault is not created |
| `MAX_ASSETS` | 10 | The `allowed_assets` of `new`: the Intents assets a mandate may pay out in | `InvalidInput`, and the vault is not created |
| `MAX_AGENTS` | 16 | Agent keys on the vault at one time, added with `add_agent` | `InvalidInput`. Remove a key with `remove_agent` first |
| `MAX_PAGE` | 100 | Items one call of `list_mandates`, `list_spends` or `list_anchors` returns. `from_index` is a position counted from 0 | None: a larger `limit` returns 100 items |
| `ONE_YOCTO` | 1 yoctoNEAR | The deposit the vault attaches to its own `ft_transfer` and `ft_withdraw` calls: in each payout, in `withdraw` and in `withdraw_intents` | None: the vault sets it |
| `USDC_STORAGE_DEPOSIT` | 1,250,000,000,000,000,000,000 yoctoNEAR (0.00125 NEAR) | What `create_mandate` passes to the USDC token's `storage_deposit` for a NEAR payee, out of the owner's deposit: the `storage_balance_bounds().min` of mainnet's USDC | `InsufficientDeposit` when the owner's deposit does not cover it and the mandate's storage |

The limits of each payment are the owner's to choose when they create a mandate. [Mandates](https://probarion.xyz/docs/concepts/mandates.md) lists every field, and [How a payment is checked](https://probarion.xyz/docs/concepts/payment-checks.md#the-14-checks-in-order) shows the order the vault checks them in, the daily backstop included.

## String and hash formats

The vault and the factory check these shapes before they store a mandate or an agent key, take a spend, record an anchor, create a vault or add a version. A malformed value fails the call. The policy engine in `@probarion/core` checks a spend's `invoice_hash` and `ref` before the SDK sends it, and the console and the CLI check both labels before they build the call.

| Input | Format | Checked by | Refused with |
| - | - | - | - |
| A mandate's `purpose_hash`, a spend's `invoice_hash` and `decision_hash`, and an anchor's `root` | 64 lowercase hex characters: a sha256 digest | `is_hex64` | `InvalidInput` |
| The `address` of a Base payee | `0x` and 40 hex digits in any case, 42 characters in all. `0X` is refused | `is_evm_address` | `InvalidInput` |
| The `address` of a Solana payee | Base58 in the Bitcoin alphabet, with no `0`, `O`, `I` or `l`, 32 to 44 characters | `is_solana_address` | `InvalidInput` |
| The `asset` of an Intents payee | Starts with `base-` for a Base payee or `sol-` for a Solana payee, and is one of the vault's `allowed_assets` | `asset_matches_chain` | `AssetNotAllowed` |
| A spend's `ref`, its idempotency key | 1 to 64 bytes. Once the vault accepts a spend, its `ref` stays used | `is_ref` | `InvalidInput`, or `DuplicateRef` for a used one |
| A mandate's `label` | At most 64 bytes | `validate_mandate` | `InvalidInput` |
| An agent key's `label` | At most 64 bytes | `add_agent` | `InvalidInput` |
| The memo of a payout to a Base or Solana payee | `WITHDRAW_TO:` and the payee's address, byte for byte. `@probarion/core` exports the same `WITHDRAW_MEMO_PREFIX` | `WITHDRAW_MEMO_PREFIX` | None: the vault writes it from the mandate |
| The memo of a payout to a NEAR payee | `probarion:` and the spend id | `NEAR_MEMO_PREFIX` | None: the vault writes it |
| The `name` of `create_vault` | 2 to 31 characters, `^[a-z0-9][a-z0-9_-]{1,30}$`. `<name>.<factory>` must also be a valid NEAR account id: no `-` or `_` at the end, never two of them in a row, and at most 64 characters in all | `valid_name` | `InvalidInput` |
| The `code_hash` of `add_version` | Base58 of 32 bytes. An `embedded` version also needs that code stored by `store_code` | `add_version` | `InvalidInput` |
| The `mode` of `add_version` | `global` or `embedded` | `add_version` | `InvalidInput` |
| The input of `store_code`: the raw vault wasm, sent with `file-args` | Not empty. The factory stores it under its sha256, which `store_code` returns | `store_code` | `InvalidInput` |

## Factory limits

The factory checks the new vault's limits before it creates anything, so a `create_vault` the vault would refuse fails in the factory and no account is made. A taken name is the one failure the factory cannot see in advance: the new account fails, and `on_vault_created` refunds the deposit from the factory's own balance.

| Constant | Value | What it limits | Past the limit |
| - | - | - | - |
| `MAX_NOTES` | 256 | Bytes of `notes` in `add_version` | `InvalidInput` |
| `MAX_PAGE` | 100 | Vaults one call of `list_vaults` returns | None: a larger `limit` returns 100 items |
| `MAX_ASSETS` | 10 | The `allowed_assets` of the factory's `new`, which every vault it creates receives | `InvalidInput` |
| `MAX_APPROVERS` | 10 | Approvers in `create_vault`, at least 1: the vault's own limit, checked before anything is created | `InvalidInput`, and nothing is created |
| `MAX_HELD_TTL_NS` | 2,592,000,000,000,000 ns (30 days) | The `held_ttl_ns` of `create_vault`, above 0: the vault's own limit, checked before anything is created | `InvalidInput`, and nothing is created |
| `min_deposit`, set in the factory's `new` | 500,000,000,000,000,000,000,000 yoctoNEAR (0.5 NEAR) on Testnet | The least `create_vault` accepts for a `global` version. An `embedded` version also charges the byte cost of the vault's copy of the code. `get_config` returns it. The Testnet factory's current version is `embedded`, so a Testnet vault needs `min_deposit` plus the code's byte cost, about 2.98501 NEAR for the 248,501-byte vault wasm, and the CLI requires `--deposit` for it | `InsufficientDeposit`, and nothing is created |

Read the factory's `min_deposit` and current version on testnet, with no key:

```bash
near contract call-function as-read-only vaults.probarion.testnet get_config json-args '{}' network-config testnet now
near contract call-function as-read-only vaults.probarion.testnet versions json-args '{}' network-config testnet now
```

## Deposits and gas per call

- **Deposit the contract asks** is what the method checks. "Exactly 1 yoctoNEAR" means any other amount, none included, fails with [`RequiresOneYocto`](https://probarion.xyz/docs/build/errors.md#RequiresOneYocto). Only a full-access key can attach a deposit, which is [why most owner calls need one](https://probarion.xyz/docs/concepts/vaults-roles-and-keys.md#why-most-owner-calls-need-exactly-1-yoctonear). A method whose deposit reads None is not `#[payable]`, and near-sdk refuses a deposit sent to it.
- **Deposit the console and the CLI attach** is what the two tools put in the transaction they prepare. Their mandate deposit has a wide margin, and [the vault refunds the rest](https://probarion.xyz/docs/concepts/mandates.md#the-deposit).
- **Prepaid gas** is the gas the console and the CLI attach, and for `spend` and `anchor` the gas the SDK attaches. The console and the CLI agree on every call they both build. A call signed by hand sets its own.

| Call | Signed by | Deposit the contract asks | Deposit the console and the CLI attach | Prepaid gas |
| - | - | - | - | - |
| `freeze` on the vault | The owner, from a full-access key or a function-call key that may call the vault | None | None | 30 Tgas |
| `unfreeze` on the vault | The owner, from a full-access key | Exactly 1 yoctoNEAR | 1 yoctoNEAR | 30 Tgas |
| `withdraw` on the vault | The owner, from a full-access key | Exactly 1 yoctoNEAR | 1 yoctoNEAR | 100 Tgas |
| `withdraw_intents` on the vault | The owner, from a full-access key | Exactly 1 yoctoNEAR | 1 yoctoNEAR | 150 Tgas |
| `create_mandate` on the vault | The owner, from a full-access key | The storage the new mandate takes at the byte cost, plus `USDC_STORAGE_DEPOSIT` for a NEAR payee. Less is `InsufficientDeposit`, and the excess is refunded to the owner | 0.05 NEAR: the console's `MANDATE_STORAGE_DEPOSIT` and the CLI's `--deposit` default | 100 Tgas |
| `revoke_mandate` on the vault | The owner, from a full-access key | Exactly 1 yoctoNEAR | 1 yoctoNEAR | 30 Tgas |
| `add_agent` on the vault | The owner, from a full-access key | Exactly 1 yoctoNEAR | 1 yoctoNEAR | 30 Tgas |
| `remove_agent` on the vault | The owner, from a full-access key | Exactly 1 yoctoNEAR | 1 yoctoNEAR | 30 Tgas |
| `set_ledger_key` on the vault | The owner, from a full-access key | Exactly 1 yoctoNEAR | 1 yoctoNEAR | 30 Tgas |
| `approve` on the vault | An approver, from a full-access key | Exactly 1 yoctoNEAR | 1 yoctoNEAR | 150 Tgas |
| `reject` on the vault | An approver, from a full-access key | Exactly 1 yoctoNEAR | 1 yoctoNEAR | 30 Tgas |
| `spend` on the vault | An agent key on the vault account. The vault's own NEAR pays the gas | None: a function-call key cannot attach one | None | 200 Tgas, the SDK's `SPEND_GAS` |
| `anchor` on the vault | The ledger key on the vault account. The vault's own NEAR pays the gas | None: a function-call key cannot attach one | None | 30 Tgas, the SDK's `ANCHOR_GAS` |
| `expire_held` on the vault | Anyone, once the hold has expired | None | Not built by a Probarion tool | Not set by a Probarion tool |
| `create_vault` on the factory | Anyone. The caller becomes the new vault's owner | At least `min_deposit`, plus the byte cost of the code for an `embedded` version. Less is `InsufficientDeposit`. The deposit stays in the vault as its NEAR, and is refunded if the name is taken | The owner's choice, at most 5 NEAR in the console. The CLI attaches `min_deposit` unless `--deposit` is given, and needs `--deposit` for an `embedded` version | 300 Tgas |
| `store_code` on the factory | The factory owner, from a full-access key | Exactly 1 yoctoNEAR | Not built by a Probarion tool: the factory owner signs it with near-cli-rs | Not set by a Probarion tool |
| `add_version` on the factory | The factory owner, from a full-access key | Exactly 1 yoctoNEAR | Not built by a Probarion tool: the factory owner signs it with near-cli-rs | Not set by a Probarion tool |
| `publish_global` on the factory | The factory owner, from a full-access key | Exactly 1 yoctoNEAR. The factory's own balance pays for the global contract | Not built by a Probarion tool: the factory owner signs it with near-cli-rs | Not set by a Probarion tool |
| `storage_deposit` on the USDC token | The owner, to register the vault on the token before funding it, or the 1Click deposit address of a top-up | Set by the token contract | 0.00125 NEAR, the console's `FT_STORAGE_DEPOSIT` | 30 Tgas |
| `ft_transfer` on the USDC token | The owner, to fund the vault with USDC, or to pay a 1Click top-up quote | Set by the token contract | 1 yoctoNEAR | 30 Tgas |

> **Owner signs**
>
> The owner signs `create_vault`, `create_mandate`, `revoke_mandate`, `add_agent`, `remove_agent`, `set_ledger_key`, `freeze`, `unfreeze`, `withdraw` and `withdraw_intents` from their own wallet, and the USDC token calls that fund the vault or pay a top-up. Their wallet pays each call's gas and deposit.
>
> _The owner signs this transaction. Probarion never signs it._

> **Approver signs**
>
> An approver signs `approve` or `reject` from their own wallet, with exactly 1 yoctoNEAR, and their wallet pays the gas.
>
> _An approver signs this transaction. Probarion never signs it._

## Gas the contracts attach

When a method calls another contract, the gas for that call comes out of the prepaid gas of the transaction that started it. That is why the calls that reach the USDC token or NEAR Intents prepay more than a plain owner call, and a payout also runs a callback. The 1 yoctoNEAR the vault attaches to a payout comes from the vault's own NEAR.

| Constant | Value | The call it pays for | Deposit attached |
| - | - | - | - |
| `GAS_FT_TRANSFER`, vault | 15 Tgas | `ft_transfer` on the USDC token: a payout to a NEAR payee, and `withdraw` | `ONE_YOCTO` |
| `GAS_FT_WITHDRAW`, vault | 100 Tgas | `ft_withdraw` on NEAR Intents: a payout to a Base or Solana payee, and `withdraw_intents` | `ONE_YOCTO` |
| `GAS_STORAGE_DEPOSIT`, vault | 10 Tgas | `storage_deposit` on the USDC token for a NEAR payee, from `create_mandate`. The vault does not wait for its result | `USDC_STORAGE_DEPOSIT` |
| `GAS_CALLBACK`, vault | 15 Tgas | The payout's callback, `on_transfer` or `on_withdraw`, which settles or releases the spend | None |
| `GAS_VAULT_NEW`, factory | 30 Tgas | `new` on the vault account that `create_vault` makes | None |
| `GAS_ON_VAULT_CREATED`, factory | 15 Tgas | The callback of `create_vault`, `on_vault_created`, which records the vault or refunds the deposit | None |

## What a builder pays

Probarion takes no fee, and there is no price list or paid plan ([Pricing](https://probarion.xyz/docs/start/what-works-today.md#pricing)). A vault costs NEAR, paid to the network, from three places:

- **The owner's wallet** pays the gas of every call it signs, the 1 yoctoNEAR most of them attach, the `create_vault` deposit, each mandate's deposit, and 0.00125 NEAR to register an account on the USDC token when funding the vault or paying a top-up. The `create_vault` deposit is not spent: it becomes the vault's own NEAR, and the vault's storage is staked out of it. A mandate's deposit pays for the mandate's storage and a NEAR payee's USDC registration, and the vault refunds the rest.
- **An approver's wallet** pays the gas of `approve` and `reject`.
- **The vault's own NEAR** pays the gas of every `spend` and `anchor`, since the agent key and the ledger key sign as the vault account. It also pays the storage each spend leaves behind, and the storage of each agent key, the ledger key and each anchor: `add_agent` and `set_ledger_key` attach only 1 yoctoNEAR. Each key's allowance caps the gas that key can burn. The vault has no method to withdraw NEAR, so NEAR sent to it stays there.

When the vault's free NEAR runs out, a spend fails with the chain's `LackBalanceForState` or `NotEnoughBalance`, not a `PROBARION:` code, and a plain NEAR transfer to the vault tops it up ([Transaction failures](https://probarion.xyz/docs/build/errors.md#transaction-failures)). The console's figures for that NEAR:

| Constant | Value | What it is |
| - | - | - |
| `STORAGE_BYTE_COST_YOCTO` | 0.00001 NEAR a byte | NEAR's storage staking: the NEAR an account keeps locked for each byte it stores |
| `NEAR_PER_SPEND_YOCTO` | 0.0053 NEAR | About what one paid spend costs the vault: the storage it leaves for good and the gas it burns. A failed spend costs less |
| `EMBEDDED_VAULT_WASM_BYTES` | 248,501 bytes | The size of the vault wasm, which an `embedded` vault stores a copy of |
| `EMBEDDED_CODE_ESTIMATE_BYTES` | 273,352 bytes | What the console counts for that copy, the wasm plus 10 percent: 2.73352 NEAR at the byte cost. What the code does not take stays in the vault |
| `FRESH_VAULT_STATE_BYTES` | 2,232 bytes | What a new vault stores besides its code, for the console's estimate of a new vault's NEAR |
| `LOW_NEAR_YOCTO` | 0.1 NEAR | Below this much free NEAR the console shows the vault's runway in amber |
| `NEAR_LOW_ALERT_YOCTO` | 0.05 NEAR | Below this much free NEAR the watcher records a `near_low` event, at most once a UTC day |
| `ALLOWANCE_LOW_ALERT_YOCTO` | 0.2 NEAR | Below this much allowance left on an agent or ledger key the watcher records an `allowance_low` event, at most once a key and UTC day |
| `MAX_CREATE_DEPOSIT_YOCTO` | 5 NEAR | The most the console attaches to `create_vault`: a taken name is refunded from the factory's own balance |
| `MAX_TOPUP_YOCTO` | 5 NEAR | The most one plain NEAR transfer to the vault sends from the console. NEAR sent to a vault does not come back out |
| `DEFAULT_TOPUP_YOCTO` | 0.5 NEAR | The top-up the console suggests |

The free NEAR is the balance minus the storage stake, `amount - storage_usage * 10^19` in yoctoNEAR. near-cli-rs shows both for any vault:

```bash
near account view-account-summary v0.probarion.testnet network-config testnet now
```

### Key allowances

An agent key and the ledger key sign as the vault account, so the gas they burn comes out of the vault's NEAR, up to the key's allowance. A key that has burned its whole allowance can no longer sign, and the owner adds a new key.

| Key | May call | Allowance the console gives it, and the CLI's default | What the vault checks |
| - | - | - | - |
| An agent key, added with `add_agent` | `spend` on the vault | 1 NEAR: the console's `VAULT_DEFAULTS.agentAllowanceYocto` and the default of `agent add --allowance`. For the Canary's vault the console asks for 3 NEAR (`CANARY_KEY_ALLOWANCES.agentAllowanceYocto`): its raw mode stops when the agent key has under 0.2 NEAR left | An allowance above 0 yoctoNEAR. An allowance of 0, an unlimited key, fails with `InvalidInput` |
| The ledger key, set with `set_ledger_key` | `anchor` on the vault | 0.25 NEAR: the console's `VAULT_DEFAULTS.ledgerAllowanceYocto` and the default of `ledger set-key --allowance`. For the Canary's vault the console asks for 2 NEAR (`CANARY_KEY_ALLOWANCES.ledgerAllowanceYocto`): the Canary does not open while the ledger key has under 0.5 NEAR left | An allowance above 0 yoctoNEAR. An allowance of 0, an unlimited key, fails with `InvalidInput` |

### Cross-chain payouts

Probarion adds no fee to a payout to a Base or Solana payee: the vault sends `ft_withdraw` the spend's amount, and its code computes no bridge or token fee. On testnet the stand-in for NEAR Intents, `intents-stub.probarion.testnet`, takes no fee. A fee that NEAR Intents or its bridge may take on mainnet is not modelled in this code, and this page does not cover it. No Base or Solana payout has run on mainnet, because spike S1 is unproven. The one mainnet vault, `v0.probarion.near`, has paid only a NEAR payee.

### Top-ups through 1Click

The console's top-up is meant to buy a vault's Base USDC balance inside NEAR Intents through 1Click. It is built for mainnet only and has not been tried with a live quote yet. It asks 1Click for the exact amount out with a 1 percent slippage tolerance, and refuses a quote that would cost more than 5 percent over that amount. The owner then pays the quote from their own wallet, with a `storage_deposit` and an `ft_transfer` on the USDC token.

## Hosted app limits

The hosted app adds limits of its own: what the Payables upload takes and reads, the mandate form, the top-up, the testnet faucet, alerts, and the browser extension's inbox and invoice queue, whose routes are Preview. During the beta its mandate form is stricter than the vault: the CLI accepts 1 to 4,294,967,295 for `--uses`, and the contract any expiry in the future.

| Constant | Value | What it is |
| - | - | - |
| `MAX_INVOICE_BYTES` | 4,194,304 bytes (4 MiB) | The largest invoice file, pasted invoice text or purpose document the console's Payables upload takes, and the largest invoice file the browser extension queues. The upload's whole request may be 64 KiB larger, for the form: `MAX_REQUEST_BYTES` in `lib/payables/upload.ts`. Past a cap, `413 too_large` |
| `MAX_TEXT_CHARS` | 50,000 | The UTF-16 units of invoice text Payables reads, shows the model and hashes: the invoice hash is the hash of exactly that text. Longer text is cut, and its amount is refused |
| `MAX_PDF_PAGES` | 20 | The pages of a PDF invoice Payables reads. The pages past them are not read or hashed, and the amount is refused |
| `MAX_USES_BETA` | 10,000 | The most payments the console's mandate form allows a mandate during the beta. The contract takes any `u32` above 0 |
| `MAX_EXPIRY_AHEAD_MS` | 31,622,400,000 ms (366 days) | How far ahead the console's mandate form lets an expiry be, during the beta. The contract asks only for a time in the future |
| `MIN_EXPIRY_AHEAD_MS` | 3,600,000 ms (1 hour) | The earliest expiry the form accepts, counted from now: time for the owner to sign before it passes |
| `MIN_TOPUP_UNITS` | 1,000,000 units (1 USDC) | The least one 1Click top-up asks for. The top-up is built for mainnet only and has not been tried with a live quote yet |
| `MAX_TOPUP_UNITS` | 1,000,000,000 units (1,000 USDC) | The most one 1Click top-up asks for, during the beta |
| `MIN_LEFT_MS` | 60,000 ms (1 minute) | A 1Click quote with less time than this left before its deadline is not offered for signing |
| `FAUCET_USDC` | 25 test USDC | What one use of the testnet faucet mints into the vault. The `faucet` limiters in the rate limits cap how often |
| Active alerts, checked in `alert_subscription_create` | 20 | The most active alerts one vault may have, email and Telegram together. Past it the console asks the owner to remove one first |
| `MAX_VAULTS` | 10 | The vaults one `GET /api/ext/inbox` answer covers, of those the account owns or approves on that network |
| `MAX_ROWS` | 10 | The invoices waiting for the owner, and the held payments, that the extension's inbox lists for each vault. Its counts include every one |
| `MAX_REPORT_BYTES` | 2,097,152 bytes (2 MiB) | The most of NEAR AI's attestation report the proof page's live TEE check (`GET /api/tee/check`) reads. A larger report is not read: the next preferred model is asked when `NEARAI_MODEL` is unset, else each check is `unavailable` |
| `MAX_ATTESTATIONS` | 4 | The model attestations of one report that the live TEE check checks, the first ones. Any past them are not checked: the answer's `attestations_total` counts them, and a pass says it covered the first of them only |

### Rate limits

Each limiter allows the hits shown in its window, for each IP address, account, vault or email address it counts. A route past its limit answers [`429 rate_limited`](https://probarion.xyz/docs/build/errors.md#http-429-rate_limited) with a `Retry-After` header, and a page or a console action shows a message instead. No window is longer than a day (`RATE_LIMIT_KEEP_S`), because a daily job deletes older counters. [HTTP API](https://probarion.xyz/docs/build/http-api.md) lists each route with its callers and errors.

| Limiter | Limit | Counted per | Applies to |
| - | - | - | - |
| `authChallenge` | 20 in a minute | IP address | `GET /api/auth/challenge`, the start of sign-in |
| `authVerify` | 10 in a minute | IP address | `POST /api/auth/verify`, the signed sign-in |
| `snapshot` | 30 in a minute | IP address, for each file | `GET /proof/<vault>/snapshot.json`, `GET /proof/<vault>/ledger.jsonl` and `GET /proof/<vault>/payments.csv` |
| `proofPage` | 60 in a minute | IP address | The public proof page, `/proof/<vault>` |
| `topupQuote` | 10 in a minute | Signed-in account and network | `POST /api/topup/quote`. The top-up is built for mainnet only and has not been tried with a live quote yet |
| `topupStatus` | 30 in a minute | Signed-in account and network | `GET /api/topup/status` |
| `topupSubmit` | 10 in a minute | Signed-in account and network | `POST /api/topup/submit` |
| `invoiceUpload` | 30 in an hour | Vault | `POST /api/console/<vault>/invoices`, the Payables upload |
| `canaryModelVisitor` | 5 in 10 minutes | IP address | `POST /api/canary/attempt`, before the model is asked |
| `canaryModelGlobal` | 300 in an hour | All visitors together | `POST /api/canary/attempt` |
| `telegramWebhook` | 120 in a minute | All calls together | `POST /api/telegram/webhook` |
| `alertTest` | 5 in 10 minutes | Vault | New alerts, emails and Telegram links on the console's alerts page, together |
| `alertLink` | 30 in a minute | IP address | The email confirmation page `/alerts/confirm` and `POST /api/alerts/confirm` |
| `alertConfirmAddress` | 3 in a day | Email address, from every vault together | The confirmation emails the alerts page sends |
| `confirmPerAccount` | 30 in a minute | Signed-in account and network | The console's chain reads for a signed transaction: its confirmation, and the block height read when the send starts, each with its own counters |
| `confirmGlobal` | 300 in a minute | All accounts together | The same reads, each with its own counter |
| `registerPerAccount` | 10 in 10 minutes | Signed-in account and network | Registering an existing vault in the console |
| `extPairPerIp` | 10 in 10 minutes | IP address and network | `POST /api/ext/pair`, the browser extension's pairing-code exchange |
| `extPairGlobal` | 300 in 10 minutes | All addresses together, per network | `POST /api/ext/pair` |
| `extInbox` | 60 in a minute | Extension token's account and network | `GET /api/ext/inbox` |
| `extInvoice` | 20 in 10 minutes | Extension token's account and network | `POST /api/ext/invoices`: invoices the browser extension queues for the owner's Confirm |
| `extMint` | 10 in 10 minutes | Signed-in account and network | Tokens and pairing codes the extension page makes, together |
| `faucetVault` | 1 in a day | Vault, each UTC day | `POST /api/topup/faucet`, the test USDC faucet on testnet |
| `faucetAccount` | 3 in a day | Signed-in owner account, each UTC day | `POST /api/topup/faucet`, the same faucet |
| `faucetGlobal` | 50 in a day | All vaults together, each UTC day | `POST /api/topup/faucet`, the same faucet |
| `faucetTries` | 10 in 10 minutes | Signed-in account | `POST /api/topup/faucet`: each press of the faucet button, before the chain is read |
| `teeCheck` | 30 in a minute | All visitors together | `GET /api/tee/check`, the proof page's live TEE check |

## SDK and core limits

These bound what `@probarion/sdk` and `@probarion/core` send, keep and wait for.

| Constant | Package | Value | What it is |
| - | - | - | - |
| `USDC_DECIMALS` | `@probarion/core` | 6 | Amounts travel in USDC's base units, so 1 USDC is `1000000` |
| `PAGE_SIZE` | `@probarion/sdk` | 50 | Items the SDK asks for in each page when it reads a whole list |
| `MAX_PAGE_LIMIT` | `@probarion/sdk` | 100 | The largest `limit` the SDK sends: the contracts' `MAX_PAGE` |
| `MAX_RESPONSE_BODY_BYTES` | `@probarion/sdk` | 65,536 bytes (64 KiB) | The largest NEAR AI response the SDK uses. The response goes into the ledger entry |
| `CATALOG_PAGE_SIZE` | `@probarion/sdk` | 100 | Models the SDK asks NEAR AI's model catalog for in each page |
| `DEFAULT_NEARAI_TIMEOUTS_MS` | `@probarion/sdk` | `catalog` 10,000 ms (10 seconds), `report` 15,000 ms (15 seconds), `chat` 90,000 ms (90 seconds), `signature` 15,000 ms (15 seconds) | How long each kind of NEAR AI call may take, headers and body together, before the SDK gives up on it. The `timeoutMs` option overrides it per kind |
| `PROPOSAL_MAX_TOKENS` | `@probarion/core` | 4,096 | The `max_tokens` of a decision request to the model |
| `MAX_REASONING_CHARS` | `@probarion/core` | 2,000 | The model's `reasoning` is cut to this many Unicode code points |
| `UNKNOWN_SETTLE_MS` | `@probarion/sdk` | 172,800,000 ms (48 hours) | How long code refuses an invoice whose spend has an unknown outcome, unless the chain shows the spend sooner |

## What the tables leave out

- The limits an owner sets for each payment and for the vault's day: [Mandates](https://probarion.xyz/docs/concepts/mandates.md) and [How a payment is checked](https://probarion.xyz/docs/concepts/payment-checks.md).
- The arguments, return values and errors of each method: [Contract reference](https://probarion.xyz/docs/build/contract-reference.md).
- The body, callers and errors of each route: [HTTP API](https://probarion.xyz/docs/build/http-api.md).
- The Canary's own caps on `POST /api/canary/attempt`, in `CANARY_LIMITS` (`apps/web/src/lib/canary/limits.ts`): attempts from one address and from everyone in an hour and a day, a daily budget of model tokens, the length of a message, and how often an attempt may go on chain. An attempt past an attempt cap or the token budget gets [`429 budget`](https://probarion.xyz/docs/build/errors.md#http-429-budget), not `rate_limited`.
- Caps the hosted app keeps on its own work and display, such as how far behind a node the health check accepts and how much of a ledger string the proof page shows.
- The NEAR protocol's own limits, such as the most gas one transaction may carry, and the price of gas.
- Mainnet values. The code is the same on both networks, but the mainnet factory is not deployed, and no mainnet `min_deposit` is recorded. The one mainnet vault, `v0.probarion.near`, was deployed without a factory. [Testnet and mainnet](https://probarion.xyz/docs/start/testnet-and-mainnet.md) explains the difference.

## Related pages

- [Vaults, roles and keys](https://probarion.xyz/docs/concepts/vaults-roles-and-keys.md): who holds which key, and the allowance on each function-call key.
- [Holds and approvals](https://probarion.xyz/docs/concepts/holds-and-approvals.md): what `approve` pays out, and when a hold expires.
- [Errors](https://probarion.xyz/docs/build/errors.md): every code the tables name.
- [Contract reference](https://probarion.xyz/docs/build/contract-reference.md): every method of the vault and the factory.
- The sources: [`contracts/vault/src/lib.rs`](https://github.com/probarion/probarion/blob/main/contracts/vault/src/lib.rs), [`contracts/factory/src/lib.rs`](https://github.com/probarion/probarion/blob/main/contracts/factory/src/lib.rs), [`apps/web/src/lib/near/runway.ts`](https://github.com/probarion/probarion/blob/main/apps/web/src/lib/near/runway.ts) and [`apps/web/src/lib/ratelimit.ts`](https://github.com/probarion/probarion/blob/main/apps/web/src/lib/ratelimit.ts).
