<!-- tempo-docs-context -->
> Source: [/docs/accounts/access-keys/spending-limits](https://tempo.xyz/developers/docs/accounts/access-keys/spending-limits.md)
> Section: [Accounts](https://tempo.xyz/developers/docs/accounts.md). Create accounts, set up signing methods, policies, access keys, key rotation, and fees, and follow guides for users, automations, agents, and teams.
> [Documentation index](https://tempo.xyz/developers/llms.txt) · [Docs skill](https://tempo.xyz/developers/SKILL.md)

> Tempo MCP: Use `search`, `find_pages`, `read_page`, and `code` at `https://mcp.tempo.xyz` for Tempo and related documentation.
> If an indexed page is missing or reflects an older site, read this site’s [documentation index](https://tempo.xyz/developers/llms.txt) and Markdown pages directly.

# Spending Limits

Caps how much of one TIP-20 token an access key can spend, such as 500 OUSD a day.

## Overview

A spending limit caps how much of one TIP-20 token an [access key](https://tempo.xyz/developers/docs/accounts/access-keys) can spend. It's one of the key's three bounds, with [expiry](https://tempo.xyz/developers/docs/accounts/access-keys/expiry) and [scopes](https://tempo.xyz/developers/docs/accounts/access-keys/scopes). Tempo reverts any transaction that would take the key over its limit.

A limit is either one-time or renews each period. To control where the money goes, use scopes.

<span id="how-it-works" />

<span id="what-counts" />

<span id="what-counts-against-the-limit" />

## Counted Outflows

A spending limit covers every TIP-20 outflow in a transaction the key signs:

* **Transfers:** Tokens the key sends count.
* **Approvals:** Approval increases count, so the key can't let a contract pull more than its limit.
* **Fees:** Fees the account pays count, unless a [fee payer](https://tempo.xyz/developers/docs/accounts/fees/fee-sponsorship) sponsors them.
* **Precompile Pulls:** Tokens that Tempo's built-in contracts (precompiles) pull from the account count.
* **Burns:** Since T12, tokens burned from the account with `burnAt` count.

Assets other than TIP-20 tokens, such as NFTs, don't count. A `transferFrom` that spends an allowance the account already granted doesn't count either. A transaction that would go over the remaining limit reverts entirely with [`SpendingLimitExceeded`](https://tempo.xyz/developers/docs/protocol/transactions/AccountKeychain#error-spendinglimitexceeded).

<span id="tip-20-spending-limits" />

<span id="per-token-spending-limits" />

<span id="one-time-and-periodic-limits" />

<span id="set-a-spending-limit" />

## Set a Limit

Pass `limits` when you [authorize the key](https://tempo.xyz/developers/docs/accounts/access-keys#authorize-an-access-key) with Viem's [`accessKey.authorize`](https://viem.sh/tempo/actions/accessKey.authorize) or [`accessKey.signAuthorization`](https://viem.sh/tempo/actions/accessKey.signAuthorization). Each entry covers one token, with the amount in base units (most USD stablecoins have 6 decimals). For example, `{ token: stablecoin, limit: parseUnits('500', 6), period: 86_400 }` allows 500 OUSD a day.

A key without `limits` spends any amount of any token. Once you pass `limits`, a token not in the list has a limit of zero. That includes fees paid in it. `limits: []` lets the key spend no TIP-20 tokens.

`period` decides whether the limit renews:

* **One-Time:** Set `period` to `0` or omit it. Once the key spends the limit, it can't spend that token again.
* **Renewing:** Set `period` to a number of seconds, such as `86_400` for a day. The first period starts when the key is authorized, not at midnight or another calendar boundary. The limit resets to its full amount when each period ends. Unspent amounts don't carry over.

<span id="read-an-access-key" />

<span id="read-the-remaining-permission" />

<span id="read-the-remaining-limit" />

<span id="remaining-limit" />

## Check the Remaining Limit

Read what a key can still spend with Viem's [`accessKey.getRemainingLimit`](https://viem.sh/tempo/actions/accessKey.getRemainingLimit). It returns two values:

* `remaining` is what the key can spend now. Once a period ends, it reads as the full limit.
* `periodEnd` is when the current period ends, as a Unix timestamp, or `0` for a one-time limit.

A missing, revoked, or expired key reads as zero.

Each payment an access key signs emits an `AccessKeySpend` event. It records the amount spent and the limit left, both in base units. The indexer shows that spend history for one key. Replace the account and key addresses with yours.

Save this query as `query.sql` and run it against the public Tempo mainnet indexer (chain ID 4217).

```sql
SELECT token, amount, remainingLimit, block_num, tx_hash
FROM AccessKeySpend
WHERE account = '0x1e0c78105f12079899f7165eb1f74891d4d0f57f'
AND publicKey = '0xb9f81dd7e629d2ec01e363c7a174c0f4ebe723e3'
ORDER BY block_num DESC
LIMIT 10
```

```bash
curl --get "https://indexer.tempo.xyz/query" \
  --data-urlencode "chainId=4217" \
  --data-urlencode "engine=clickhouse" \
  --data-urlencode "signature=AccessKeySpend(address indexed account, address indexed publicKey, address indexed token, uint256 amount, uint256 remainingLimit)" \
  --data-urlencode "sql@query.sql"
```

<span id="change-an-access-key" />

<span id="change-a-spending-limit" />

## Change a Limit

Enough signers to reach the threshold, or an [admin key](https://tempo.xyz/developers/docs/accounts/access-keys/admin-access-keys), change a key's limit without revoking it. Set the new limit with Viem's [`accessKey.updateLimit`](https://viem.sh/tempo/actions/accessKey.updateLimit).

The update sets both the limit and what's left of it to the new value. Later periods renew to the new value. For example, a key has spent 400 of its 500 OUSD today. Updating it to `parseUnits('600', 6)` lets it spend 600 more today, not 100. It then spends 600 a day after that. The period and the current period's end stay the same. On a key with no limits, the update turns limits on.

<span id="spending-limit-limits" />

## Limits

* A limited access key can't change limits, including its own.
* `updateLimit` reverts on a revoked key ([`KeyAlreadyRevoked`](https://tempo.xyz/developers/docs/protocol/transactions/AccountKeychain#error-keyalreadyrevoked)) or an expired key ([`KeyExpired`](https://tempo.xyz/developers/docs/protocol/transactions/AccountKeychain#error-keyexpired)). It also reverts on an admin key ([`InvalidKeyId`](https://tempo.xyz/developers/docs/protocol/transactions/AccountKeychain#error-invalidkeyid)), since admin keys have no limits.

Specification: [Account Keychain spending limits](https://tempo.xyz/developers/docs/protocol/transactions/AccountKeychain#spending-limit-enforcement).

## Related

[Access Keys](https://tempo.xyz/developers/docs/accounts/access-keys): Covers how access keys sign for an account within their bounds.

[Scopes](https://tempo.xyz/developers/docs/accounts/access-keys/scopes): Covers which contracts, functions, and recipients a key can use.

[Expiry](https://tempo.xyz/developers/docs/accounts/access-keys/expiry): Covers when a key stops working and how to replace it.

[Fee Sponsorship](https://tempo.xyz/developers/docs/accounts/fees/fee-sponsorship): Covers fee payers, whose sponsored fees don't count against a limit.
