Infrastructure · feature guide

The AI gateway for mobile apps.

An AI gateway is a server-side proxy between your app and model providers. Your mobile app calls the gateway with its Amba session; the gateway holds your OpenAI, Anthropic, Mistral, or Google key server-side, applies per-prompt spend budgets and per-user rate limits, then forwards the request and returns the provider’s response.

Get an API key All featuresupdated June 12, 2026
the agent path:

Any key you ship inside a mobile binary is public — extraction from a decompiled app is routine, and a leaked model-provider key bills until you notice. The standard fix is a proxy you write, deploy, and harden yourself. Amba ships that proxy as a feature of the backend you already have: register your provider key once server-side, register named prompts (system prompt, model, token cap, rate limit), and your app invokes them by slug through the SDK with the user’s session attached. The prompt content never ships in the client bundle, every call is attributed to a user, usage is metered per call, and three independent spend controls — per-prompt budgets, per-user rate limits, and a project billing ceiling — keep an exposed endpoint from becoming an open tab.

How do I hide my API key in a mobile app?

You can’t — not inside the app. Obfuscation, splitting, and "encrypted" embedding all end the same way: the binary is on the attacker’s device, so the key is too. The only durable answer is that the key never enters the binary: the app authenticates to your backend as a user, and the backend calls the provider with a key it alone holds. Amba’s gateway is that path with the operational layer included — per-user attribution, rate limits, budgets, and usage metering — rather than a bare passthrough you would still need to build controls around.

What are server-registered prompts?

A prompt is a named, versioned server-side definition: provider, model, system prompt, max output tokens, an optional per-user rate limit, and a client_invokable flag. The app references it by slug — Amba.ai.anthropic.messages.create({ prompt_slug: "support_assistant", variables: {...} }) — and the server fills in everything else. That keeps the system prompt out of the bundle (it is IP, and it is tamperable client-side), and makes model swaps and prompt revisions a server-side version bump instead of an app release. Updates increment the version; nothing redeploys.

Which model providers can the gateway proxy to?

Anthropic, OpenAI, Mistral, and Google Gemini, as of mid-2026 — you bring your own key per provider, registered once with amba_ai_providers_set and stored server-side. Responses return the provider’s native shape verbatim, streaming is supported token-by-token, and vision input is mapped to each provider’s native image format for you. Every call also emits a usage event with input and output token counts, so per-user cost attribution comes free.

How do spend controls work?

Three layers, independently set. Per-prompt budgets (amba_ai_prompts_set_budget) cap what one named prompt can spend per day, month, or in total — at the cap, invocations are denied with a structured ai_budget_exceeded error instead of reaching the provider. Per-user rate limits (the rate_limit on the prompt definition) cap invocations per user (or session) per window — the default shape is 20 per 60 seconds keyed by user_id. And the project billing ceiling (amba_billing_set_ceiling) caps the whole project’s monthly bill, with warning webhooks at 80% and 100%. To be precise: budgets are per-prompt, limits are per-user — there is no per-user dollar budget primitive as of mid-2026.

The three spend-control layers
ControlScopeTool / fieldAt the limit
Spend budgetOne named prompt, per day / month / totalamba_ai_prompts_set_budget (budget_usd, budget_period)Invocations denied with ai_budget_exceeded until the period resets
Rate limitOne user or session, per window, per promptrate_limit { window, max, key } on the prompt definitionRequests over max per window are rejected (defaults: 20 per 60s by user_id)
Billing ceilingThe whole project’s monthly billamba_billing_set_ceiling (ceiling_usd)Metered writes return 402 with a machine-readable payload; reads keep working

Tool names, defaults, and error codes verified against the live tool registry, June 2026. Budgets are per-prompt; limits are per-user — they compose, they are not the same control.

how it works

How do I set up the gateway end to end?

Provider key → prompt → budget — three tool calls

1. amba_ai_providers_set
   { "project_id": "...", "provider": "anthropic",
     "api_key": "<your provider key — stored server-side>", "pat": "..." }

2. amba_ai_prompts_create
   { "project_id": "...", "name": "support_assistant",
     "provider": "anthropic", "model": "claude-sonnet-4-5-20250929",
     "system_prompt": "You are a concise support agent for ...",
     "max_tokens": 1024,
     "rate_limit": { "window": "60s", "max": 20, "key": "user_id" },
     "client_invokable": true, "pat": "..." }

3. amba_ai_prompts_set_budget
   { "project_id": "...", "name": "support_assistant",
     "budget_usd": 25, "budget_period": "monthly", "pat": "..." }

Check headroom any time:
   amba_ai_prompts_get_spend { "project_id": "...",
     "name": "support_assistant", "pat": "..." }
   → { spend_usd, budget_usd, exceeded, period_start }

client_invokable: true is what allows end-user SDK code to invoke the prompt; it defaults to false (server-side only). Providers: anthropic, openai, mistral, gemini.

in the app

What does the client call look like?

Invoke by slug — no key, no model id, no system prompt in the bundle

import { Amba } from '@layers/amba-web';

const reply = await Amba.ai.anthropic.messages.create({
  prompt_slug: 'support_assistant',
  variables: { user_query: 'How do I cancel?' },
});
// reply is the provider's native response shape, verbatim

// Or stream tokens as they arrive:
let answer = '';
for await (const ev of Amba.ai.anthropic.messages.stream({
  prompt_slug: 'support_assistant',
  variables: { user_query: 'How do I cancel?' },
})) {
  if (ev.type === 'delta') answer += ev.text;
}

Verified against the published SDK surface, June 2026. Each call emits a usage event with token counts, attributed to the calling user.

the tools

Which MCP tools cover this surface?

toolwhat it does
amba_ai_providers_setRegister or rotate a provider key (stored server-side)
amba_ai_providers_listList which providers have keys registered
amba_ai_prompts_createRegister a named, versioned prompt: model, system prompt, limits
amba_ai_prompts_invokeServer-side test invocation of a registered prompt
amba_ai_prompts_set_budgetCap one prompt’s spend per day / month / total
amba_ai_prompts_get_spendRead current-period spend, budget, and headroom
the honest part

When is this not the right call?

Calling from your own server? Go direct
If the AI call originates server-side in a backend you already run, your key is already private — a gateway adds a hop without a custody win. The gateway earns its place when calls originate from client devices, or when you want its per-user attribution, budgets, and rate limits without building them.
Provider coverage is four providers, as of mid-2026
Anthropic, OpenAI, Mistral, and Google Gemini are wired today. If your model runs elsewhere — a self-hosted open-weights deployment, a niche provider — the gateway cannot proxy it yet, and a direct integration is the honest answer.
Bleeding-edge provider betas may need direct calls
The gateway proxies the providers’ standard message surfaces and returns responses verbatim. Day-zero beta features outside those surfaces can lag — if your product depends on a provider beta the moment it ships, keep that path direct (server-side) and route the steady-state traffic through the gateway.
the agent path

Can an AI agent set this up end to end?

Yes. Amba’s hosted MCP server at https://mcp.amba.dev/mcp (Streamable HTTP) exposes the whole backend as tool calls. amba_developer_signup mints a developer token and a provisioned project — client key and server key included — with no browser, and the project goes active in about ten seconds. The agent registers your provider key, defines the prompt with its rate limit, sets the budget, and test-invokes it — four tool calls — then writes the one-line SDK invocation into the app.

questions

AI GatewayFAQ

How do I hide my OpenAI or Anthropic API key in a mobile app?

You don’t put it in the app at all — any key in the binary is extractable. Route calls through a server-side gateway: your app authenticates as a user with its session, and the gateway holds the provider key, applies limits, and forwards the request. Amba ships this as amba_ai_providers_set plus named prompts the SDK invokes by slug.

What stops one user from running up my AI bill?

Per-user rate limits — each prompt carries a rate_limit (window, max, key), defaulting to 20 invocations per 60 seconds keyed by user_id. Above that, per-prompt budgets cap total spend per day, month, or all time (denied with ai_budget_exceeded at the cap), and the project billing ceiling bounds the whole monthly bill.

Are budgets set per user or per prompt?

Per prompt. amba_ai_prompts_set_budget caps what one named prompt can spend in a period — and per-user control is the rate limit, which caps invocations per user per window. The two compose: a prompt with a $25 monthly budget and a 20-per-minute user limit bounds both the total bill and any single user’s share. There is no per-user dollar budget primitive as of mid-2026.

Which AI providers does the gateway support?

Anthropic, OpenAI, Mistral, and Google Gemini as of mid-2026, each with your own key registered server-side via amba_ai_providers_set. Responses come back in the provider’s native shape, streaming and vision input are supported, and every call is metered with token counts attributed to the calling user.

Why keep the system prompt server-side?

Because it is both intellectual property and an attack surface. A system prompt shipped in the bundle can be read by competitors and tampered with by users. Server-registered prompts keep it out of the client entirely, version every revision, and let you change models or wording without an app-store release.

When should I call the provider directly instead?

When the call originates from your own server (the key is already private), when your model is not among the four supported providers, or when you depend on a day-zero provider beta outside the standard message surfaces. Client-originated calls are where the gateway is the right default.

start in 30 seconds

Hand the docs to your agent.
Ship by lunch.

Read the docs