{"slug":"set-a-team-wide-budget","title":"Set a team-wide budget","tags":["tailscale"],"agent_summary":"Last validated: Apr 9, 2026","trigger_phrases":[],"runnable":false,"markdown":"\r\n# Set a team-wide budget\r\n\r\nLast validated: Apr 9, 2026\r\n\r\nAperture by Tailscaleis currently [in alpha](https://tailscale.com/docs/reference/tailscale-release-stages#alpha).\r\n\r\nPer-user spending limits prevent individual overuse, but they do not cap total organizational spend. A team-wide budget creates a single shared quota bucket that all users draw from, so your organization's aggregate AI costs stay within a defined ceiling.\r\n\r\nYou can use a team-wide budget on its own or combine it with [per-user spending limits](https://tailscale.com/docs/aperture/how-to/set-per-user-spending-limits) for layered cost control. When a grant references multiple quota buckets, all buckets must have a positive balance for a request to proceed.\r\n\r\n## [Prerequisites](https://tailscale.com/docs/aperture/how-to/set-team-budget\\#prerequisites)\r\n\r\nBefore you begin, ensure you have the following:\r\n\r\n- An [Aperture instance](https://tailscale.com/docs/aperture/get-started) with at least one provider configured.\r\n- Admin access to the [Aperture configuration](https://tailscale.com/docs/aperture/configuration).\r\n\r\n## [Define a shared quota bucket](https://tailscale.com/docs/aperture/how-to/set-team-budget\\#define-a-shared-quota-bucket)\r\n\r\nOpen the **Settings** page in the [Aperture dashboard](https://tailscale.com/docs/aperture/reference/dashboard) and add a shared bucket to the `quotas` section of your configuration. A shared bucket uses a fixed name without template variables, so all requests draw from the same balance:\r\n\r\n```json\r\n\"quotas\": {\r\n  \"team-monthly\": {\r\n    \"capacity\": \"$500.00\",\r\n    \"rate\": \"$500.00/month\",\r\n    \"on_exceed\": \"reject\"\r\n  }\r\n}\r\n```\r\n\r\nThis creates a single bucket called `team-monthly` with a $500 capacity that refills at $500 per month (30 days). Every request that references this bucket deducts from the same balance regardless of which user sent the request.\r\n\r\nThe `capacity` field sets the maximum balance. The `rate` field controls the refill speed. Supported time units are `min`, `hour`, `day`, `week`, and `month` (30 days). When `on_exceed` is `\"reject\"`, Aperture blocks requests that would bring the bucket below zero and returns HTTP 429 with a `Retry-After` header.\r\n\r\n`\"reject\"` is the only supported value for `on_exceed`.\r\n\r\n## [Attach the budget to a grant](https://tailscale.com/docs/aperture/how-to/set-team-budget\\#attach-the-budget-to-a-grant)\r\n\r\nAdd the shared bucket to the `quotas` array in your grant. The following example applies the team budget to all users and all models:\r\n\r\n```json\r\n\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"*\"],\\\r\n    \"app\": {\\\r\n      \"tailscale.com/cap/aperture\": [\\\r\n        { \"role\": \"user\" },\\\r\n        {\\\r\n          \"models\": \"**\",\\\r\n          \"quotas\": [\\\r\n            {\"bucket\": \"team-monthly\"}\\\r\n          ]\\\r\n        }\\\r\n      ]\\\r\n    }\\\r\n  }\\\r\n]\r\n```\r\n\r\n## [Combine with per-user limits](https://tailscale.com/docs/aperture/how-to/set-team-budget\\#combine-with-per-user-limits)\r\n\r\nTo enforce both a per-user daily limit and a team-wide monthly cap, define both buckets and reference them in the same grant:\r\n\r\n```json\r\n\"quotas\": {\r\n  \"daily:<user>\": {\r\n    \"capacity\": \"$10.00\",\r\n    \"rate\": \"$5.00/day\",\r\n    \"on_exceed\": \"reject\"\r\n  },\r\n  \"team-monthly\": {\r\n    \"capacity\": \"$500.00\",\r\n    \"rate\": \"$500.00/month\",\r\n    \"on_exceed\": \"reject\"\r\n  }\r\n},\r\n\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"*\"],\\\r\n    \"app\": {\\\r\n      \"tailscale.com/cap/aperture\": [\\\r\n        { \"role\": \"user\" },\\\r\n        {\\\r\n          \"models\": \"**\",\\\r\n          \"quotas\": [\\\r\n            {\"bucket\": \"daily:<user>\"},\\\r\n            {\"bucket\": \"team-monthly\"}\\\r\n          ]\\\r\n        }\\\r\n      ]\\\r\n    }\\\r\n  }\\\r\n]\r\n```\r\n\r\nWhen a grant references multiple quota buckets, Aperture checks all of them before forwarding the request. If any single bucket is exhausted, Aperture rejects the request even if the other buckets have remaining balance. After the response completes, Aperture deducts the estimated cost from every referenced bucket.\r\n\r\n## [Verify the configuration](https://tailscale.com/docs/aperture/how-to/set-team-budget\\#verify-the-configuration)\r\n\r\nAfter saving the configuration, confirm the budget is active:\r\n\r\n1. Send a test request through Aperture.\r\n2. Check the [quota status](https://tailscale.com/docs/aperture/how-to/check-and-refill-budgets) using the API (`GET /api/quotas`) or the **Models** page in the Aperture dashboard. The `team-monthly` bucket should appear with the correct capacity and a balance reduced by the cost of your test request.\r\n\r\n## [Next steps](https://tailscale.com/docs/aperture/how-to/set-team-budget\\#next-steps)\r\n\r\n- [Set per-user spending limits](https://tailscale.com/docs/aperture/how-to/set-per-user-spending-limits) to prevent individual users from consuming a disproportionate share of the team budget.\r\n- [Check and refill budgets](https://tailscale.com/docs/aperture/how-to/check-and-refill-budgets) to monitor the team bucket balance and manually add funds if needed.\r\n- Refer to the [quotas configuration reference](https://tailscale.com/docs/aperture/configuration#quotas) for the complete field reference and additional examples.\r\n\r\n![Project Logo](https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed)\r\n\r\nAsk AI\r\n\r\nreCAPTCHA\r\n\r\nRecaptcha requires verification.\r\n\r\nprotected by **reCAPTCHA**\r\n","html":"<h1>Set a team-wide budget</h1>\n<p>Last validated: Apr 9, 2026</p>\n<p>Aperture by Tailscaleis currently <a href=\"https://tailscale.com/docs/reference/tailscale-release-stages#alpha\">in alpha</a>.</p>\n<p>Per-user spending limits prevent individual overuse, but they do not cap total organizational spend. A team-wide budget creates a single shared quota bucket that all users draw from, so your organization's aggregate AI costs stay within a defined ceiling.</p>\n<p>You can use a team-wide budget on its own or combine it with <a href=\"https://tailscale.com/docs/aperture/how-to/set-per-user-spending-limits\">per-user spending limits</a> for layered cost control. When a grant references multiple quota buckets, all buckets must have a positive balance for a request to proceed.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/how-to/set-team-budget#prerequisites\">Prerequisites</a></h2>\n<p>Before you begin, ensure you have the following:</p>\n<ul>\n<li>An <a href=\"https://tailscale.com/docs/aperture/get-started\">Aperture instance</a> with at least one provider configured.</li>\n<li>Admin access to the <a href=\"https://tailscale.com/docs/aperture/configuration\">Aperture configuration</a>.</li>\n</ul>\n<h2><a href=\"https://tailscale.com/docs/aperture/how-to/set-team-budget#define-a-shared-quota-bucket\">Define a shared quota bucket</a></h2>\n<p>Open the <strong>Settings</strong> page in the <a href=\"https://tailscale.com/docs/aperture/reference/dashboard\">Aperture dashboard</a> and add a shared bucket to the <code>quotas</code> section of your configuration. A shared bucket uses a fixed name without template variables, so all requests draw from the same balance:</p>\n<pre><code class=\"language-json\">\"quotas\": {\r\n  \"team-monthly\": {\r\n    \"capacity\": \"$500.00\",\r\n    \"rate\": \"$500.00/month\",\r\n    \"on_exceed\": \"reject\"\r\n  }\r\n}\n</code></pre>\n<p>This creates a single bucket called <code>team-monthly</code> with a $500 capacity that refills at $500 per month (30 days). Every request that references this bucket deducts from the same balance regardless of which user sent the request.</p>\n<p>The <code>capacity</code> field sets the maximum balance. The <code>rate</code> field controls the refill speed. Supported time units are <code>min</code>, <code>hour</code>, <code>day</code>, <code>week</code>, and <code>month</code> (30 days). When <code>on_exceed</code> is <code>\"reject\"</code>, Aperture blocks requests that would bring the bucket below zero and returns HTTP 429 with a <code>Retry-After</code> header.</p>\n<p><code>\"reject\"</code> is the only supported value for <code>on_exceed</code>.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/how-to/set-team-budget#attach-the-budget-to-a-grant\">Attach the budget to a grant</a></h2>\n<p>Add the shared bucket to the <code>quotas</code> array in your grant. The following example applies the team budget to all users and all models:</p>\n<pre><code class=\"language-json\">\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"*\"],\\\r\n    \"app\": {\\\r\n      \"tailscale.com/cap/aperture\": [\\\r\n        { \"role\": \"user\" },\\\r\n        {\\\r\n          \"models\": \"**\",\\\r\n          \"quotas\": [\\\r\n            {\"bucket\": \"team-monthly\"}\\\r\n          ]\\\r\n        }\\\r\n      ]\\\r\n    }\\\r\n  }\\\r\n]\n</code></pre>\n<h2><a href=\"https://tailscale.com/docs/aperture/how-to/set-team-budget#combine-with-per-user-limits\">Combine with per-user limits</a></h2>\n<p>To enforce both a per-user daily limit and a team-wide monthly cap, define both buckets and reference them in the same grant:</p>\n<pre><code class=\"language-json\">\"quotas\": {\r\n  \"daily:&#x3C;user>\": {\r\n    \"capacity\": \"$10.00\",\r\n    \"rate\": \"$5.00/day\",\r\n    \"on_exceed\": \"reject\"\r\n  },\r\n  \"team-monthly\": {\r\n    \"capacity\": \"$500.00\",\r\n    \"rate\": \"$500.00/month\",\r\n    \"on_exceed\": \"reject\"\r\n  }\r\n},\r\n\"grants\": [\\\r\n  {\\\r\n    \"src\": [\"*\"],\\\r\n    \"app\": {\\\r\n      \"tailscale.com/cap/aperture\": [\\\r\n        { \"role\": \"user\" },\\\r\n        {\\\r\n          \"models\": \"**\",\\\r\n          \"quotas\": [\\\r\n            {\"bucket\": \"daily:&#x3C;user>\"},\\\r\n            {\"bucket\": \"team-monthly\"}\\\r\n          ]\\\r\n        }\\\r\n      ]\\\r\n    }\\\r\n  }\\\r\n]\n</code></pre>\n<p>When a grant references multiple quota buckets, Aperture checks all of them before forwarding the request. If any single bucket is exhausted, Aperture rejects the request even if the other buckets have remaining balance. After the response completes, Aperture deducts the estimated cost from every referenced bucket.</p>\n<h2><a href=\"https://tailscale.com/docs/aperture/how-to/set-team-budget#verify-the-configuration\">Verify the configuration</a></h2>\n<p>After saving the configuration, confirm the budget is active:</p>\n<ol>\n<li>Send a test request through Aperture.</li>\n<li>Check the <a href=\"https://tailscale.com/docs/aperture/how-to/check-and-refill-budgets\">quota status</a> using the API (<code>GET /api/quotas</code>) or the <strong>Models</strong> page in the Aperture dashboard. The <code>team-monthly</code> bucket should appear with the correct capacity and a balance reduced by the cost of your test request.</li>\n</ol>\n<h2><a href=\"https://tailscale.com/docs/aperture/how-to/set-team-budget#next-steps\">Next steps</a></h2>\n<ul>\n<li><a href=\"https://tailscale.com/docs/aperture/how-to/set-per-user-spending-limits\">Set per-user spending limits</a> to prevent individual users from consuming a disproportionate share of the team budget.</li>\n<li><a href=\"https://tailscale.com/docs/aperture/how-to/check-and-refill-budgets\">Check and refill budgets</a> to monitor the team bucket balance and manually add funds if needed.</li>\n<li>Refer to the <a href=\"https://tailscale.com/docs/aperture/configuration#quotas\">quotas configuration reference</a> for the complete field reference and additional examples.</li>\n</ul>\n<p><img src=\"https://cdn.brandfetch.io/tailscale.com/fallback/lettermark/theme/dark/h/256/w/256/icon?c=1bfwsmEH20zzEfSNTed\" alt=\"Project Logo\"></p>\n<p>Ask AI</p>\n<p>reCAPTCHA</p>\n<p>Recaptcha requires verification.</p>\n<p>protected by <strong>reCAPTCHA</strong></p>\n"}