---
title: "Give Teams Scoped AI Access Without Separate Infrastructure"
description: "Most teams choose between one shared provider key everyone can drain or a separate gateway per team to babysit. The Zuplo AI Gateway scopes each team to the providers, models, and budget you assign, from one place."
canonicalUrl: "https://zuplo.com/blog/2026/07/16/give-teams-scoped-ai-access-without-separate-infrastructure"
pageType: "blog"
date: "2026-07-16"
authors: "martyn"
tags: "AI Gateway, API Security"
image: "https://zuplo.com/og?text=Give%20Teams%20Scoped%20AI%20Access%20Without%20Separate%20Infrastructure"
---
Your data team wants Claude. Your support bot needs GPT-4o on a tight leash.
Marketing wants to try whatever is cheap this week. You have one OpenAI key and
one Anthropic key, and every team shares them. So every team can drain them,
your monthly invoice is a single number nobody can attribute, and a leaked key
hands an attacker every model you pay for.

The instinct is to split things up: a proxy per team, its own provider account,
separate budgets. That is more infrastructure to deploy, more credentials to
rotate, and more dashboards to watch, all to solve an access-control problem
that was never about infrastructure.

<CalloutAudience
  variant="useIf"
  items={[
    `Several teams or apps share the same OpenAI, Anthropic, or other provider keys`,
    `You want per-team budgets and usage you can actually attribute`,
    `You are tempted to run a separate gateway or proxy per team`,
    `You need provider credentials to live in one place, not in every team's env`,
  ]}
/>

## Two bad options: a shared key or a gateway per team

The shared key is the path of least resistance and the one most teams are on. No
isolation: any app can call any model, no budget belongs to anyone, the bill
arrives as one undifferentiated total, and a leak exposes every provider at
once.

The other option is a slice of infrastructure per team. It isolates teams, but
the cost is a separate deployment, provider account, and key set to rotate,
multiplied by every team you have. You traded an access-control problem for an
operations problem.

| | Shared provider key | Gateway per team |
| --- | --- | --- |
| Team isolation | None | Yes |
| Per-team budget | No | Yes, but managed separately |
| Bill attribution | One total | Per deployment |
| Leak blast radius | Every provider | One team |
| Operational cost | Low | Deployment, account, and keys per team |

The goal is per-team scope, and scope does not require a second gateway. This is
the same least-privilege posture covered in
[zero-trust API security](https://zuplo.com/learning-center/zero-trust-api-security):
isolate access at the boundary instead of multiplying the boundaries.

## Configure your AI providers once

A Zuplo AI Gateway lives inside a single Zuplo project, and that is where the
real provider credentials live. Open **Settings → AI Providers**, click **Add
Provider**, pick the provider (OpenAI, Anthropic, Google, Mistral, xAI, or any
OpenAI-compatible endpoint), paste its API key, and select which models to
expose. Do this once per provider, and the whole gateway draws on it.

That single step removes the infrastructure question. There is no per-team
provider account and no provider key in a team's environment variables. The
credential that can spend money is stored once in the project, and every team
consumes it through the gateway rather than holding it.

## Scope each team to its own providers and limits

Teams carve that shared pool into isolated slices. Providers attach to a team,
apps belong to a team, and each app gets its own key, so a team is the hinge the
whole model turns on. On the **Teams** tab, click **Create Team** and name it,
and you have an organizational unit that owns access to specific providers and
apps. You always have at least one team at the top of the hierarchy, the root
team that represents the whole organization. Sub-teams are optional, nested
underneath when you want per-department or per-squad caps.

That ownership scopes everything beneath it. Assign Claude to the data team and
GPT-4o to the support team, and the two are genuinely separate even though both
resolve to the upstream credentials you configured once. On plans with
role-based access control, two roles govern who manages that boundary: a
**Member** uses the team's assigned providers and apps, while an **Admin** can
also change settings and membership. RBAC is an enterprise add-on.

[//]:
  #
  "TODO screenshot: AI Gateway Teams view showing a root team and a sub-team with their assigned providers. Save to public/blog-images/2026-07-16-give-teams-scoped-ai-access-without-separate-infrastructure/teams-providers.png. Alt: The Zuplo AI Gateway Teams tab showing a root team and a nested sub-team, each with its own assigned AI providers."

## Give every app its own key and gateway URL

A team is the access boundary; an app is the unit you hand to a workload. On the
**Apps** tab, click **Create App**, give it a name, assign it to a team, and
pick its completions model from the providers its team is assigned (plus an
embeddings model if the app does retrieval, like RAG over your own docs). An app
can only choose from
what its team owns, so the team boundary already does its job at create time.
Each app comes out with two things: its own **Zuplo-managed API key** and its
own gateway URL.

The key is where the team scope becomes a runtime control. It is a Zuplo key,
not your provider key, so the app never sees the OpenAI or Anthropic credential
behind it, and because the app belongs to a team, the key can only reach the
providers that team was assigned. Rotate or revoke an app's key and you cut off
exactly one workload without touching anyone else or re-keying a provider. Each
app's dashboard shows its own spend and request volume, so the bill reads by app
instead of arriving as one anonymous total.

Apps talk to the gateway through a [Universal
API](https://zuplo.com/docs/ai-gateway/universal-api): the app's URL and request
shape stay the same whatever provider sits behind it. Moving the support bot
from GPT-4o to Claude is a change in the app's configuration, not a code change
the team has to ship.

## Cap spend with budgets that cascade down

Scope is not just which models a team can reach, it is how much they can spend.
Open the **Usage & Limits** tab on any team or app and set a **Daily Budget** or
monthly budget. Budgets cascade and a child can never exceed its parent: a Root
Team capped at $1,000/day can hold a sub-team at $500/day, which can hold a
single app at $10/day. Raising the app's cap above its team's is not allowed, so
a runaway workload cannot quietly consume the whole organization's budget.

Each limit runs in one of two modes. **Enforce** blocks requests once the budget
is hit and returns an error. **Warn** lets requests through but fires a
notification, the safer default while you learn what a team consumes before you
start rejecting traffic. We run our own internal tools through this gateway, and
every new app starts at a low daily cap in Warn mode for its first week; we have
watched a runaway batch job trip the warning long before it touched the invoice.

| Level     | Example cap | What it bounds                       |
| --------- | ----------- | ------------------------------------ |
| Root Team | $1,000/day  | The whole organization               |
| Sub-Team  | $500/day    | One department, capped by the root   |
| App       | $10/day     | One workload, capped by its sub-team |

[//]:
  #
  "TODO screenshot: Usage & Limits tab on a team or app showing the Daily Budget field and the Enforce/Warn mode toggle. Save to public/blog-images/2026-07-16-give-teams-scoped-ai-access-without-separate-infrastructure/usage-limits.png. Alt: The Zuplo AI Gateway Usage and Limits tab with a Daily Budget field set and the enforcement mode toggled between Enforce and Warn."

<CalloutTip variant="mistake">
  Start every new team in **Warn** mode. Switch to **Enforce** once you have a
  week of real usage and know where the ceiling should sit. Enforcing a budget
  you guessed at is how you page yourself at 2am because a legitimate job hit a
  number you invented.
</CalloutTip>

## One gateway, scoped per team

Before: one shared key, no per-team budget, no attribution, and a leak that
exposes every provider you pay for. After: providers configured once, each team
scoped to its own models, each app carrying its own revocable key and its own
budget that cannot overrun the parent, and a single bill you can read by team
and by app.

None of that required a second deployment. The isolation people reach for
separate infrastructure to get is an access model the gateway already draws for
you, the same buy-versus-build math we walked through for
[MCP gateways](https://zuplo.com/blog/mcp-gateway-buy-or-build). For per-tool
scoping on the agent side, the
[capability filter](https://zuplo.com/blog/expose-only-mcp-tools-you-choose)
does the equivalent for MCP servers. Decide the scope when you create the team,
not after a workload has found the edge of a shared key.

<CalloutSignup
  badge="AI Gateway"
  title="Scope your first team in the AI Gateway"
  description="Configure your providers once, then give each team its own models, keys, and budget from a single gateway. No separate deployment per team."
  features={[
    "Provider credentials stored once, never exposed to teams",
    "Per-app keys and gateway URLs you can revoke independently",
    "Cascading daily and monthly budgets with enforce or warn",
  ]}
  signupButtonText="Spin up a project"
  signupUrl="https://portal.zuplo.com/signup?utm_source=zuplo-blog&utm_medium=web&utm_campaign=ai-gateway"
  secondaryAction={{
    text: "Read the AI Gateway docs",
    href: "https://zuplo.com/docs/ai-gateway/introduction",
  }}
/>