Hard caps at every scope
Per org, key, SKU, environment, agent and agent session; per day and per month. All checked atomically, so parallel requests cannot slip past together.
A proxy for paid APIs
Swap one base URL and one key. Every call is priced per SKU, checked against your caps
in one atomic step, and refused with a clear 402 once a cap would be
crossed. Google Maps Platform first; Twilio, Mapbox, HERE, Tavily, Exa, Brave and
SerpApi built in.
Free plan: 1 key and $50/month of protected spend, no card. Or
self-host the Apache-2.0 core with one
docker compose.
- https://maps.googleapis.com/maps/api/geocode/json + https://proxy.spendbrake.dev/google-maps/maps/api/geocode/json - ?address=Sofia&key=AIza… + ?address=Sofia&key=sb_live_… HTTP/1.1 200 OK X-Brake-Cost-Micros: 5000 X-Brake-Remaining-Micros: 3000 … the next call would cross the cap: HTTP/1.1 402 Payment Required {"error":"budget_exceeded", "message":"Spend cap reached for org. Stop and ask the user to raise the cap.", "scope":"org","window":"d:20261029","cap":5000000,"spent":4997000, "resetsAt":"2026-10-30T00:00:00.000Z"}
How it works
You keep your provider account and your own key. Spend Brake stores it encrypted,
forwards each request with it, and hands your apps and agents
sb_live_… keys you can cap, scope and kill.
The virtual key is checked (cached 5 s) along with its environment, agent and session.
SKU from the path and field mask, worst case in micro-dollars, from price files that cite their source.
One Lua call on Valkey: kill switch, loop breaker, and a reservation against every cap at once.
The real key is decrypted locally and never logged. Responses stream through; nothing is cached.
The actual cost replaces the reservation and a usage event lands in the ledger, in the background.
app / agent → proxy → provider, then
Valkey → worker → Postgres ledger → alerts → webhooks / email. Valkey down
means fail closed (503) unless a key opts into a small fail-open allowance.
What you get
Per org, key, SKU, environment, agent and agent session; per day and per month. All checked atomically, so parallel requests cannot slip past together.
Google Maps Platform Places, Geocoding and Routes priced per field mask; Twilio settled at its final price. A daily check watches provider price pages for drift.
One call, link or button stops a key, a provider, a session or the whole org immediately. Alerts carry signed Kill, Raise and Mute links so you can act from your phone.
A circuit trips when a key repeats identical requests, or a session pumps calls,
past your rule. The caller gets 429 loop_detected with a retry time,
and you get an alert.
Signed webhooks with Slack, Discord and Teams presets or raw JSON, plus email. Thresholds, kills, loops and price changes, each with one-click actions.
Your own Prometheus endpoint at GET /v1/metrics: requests by outcome,
cost, refunds, latency histograms and live budget. OpenTelemetry export sends every
call as a span to your collector, joined to the caller's trace.
brake CLI
brake init sets up an org, stores the provider key and prints the exact
Google Cloud steps to restrict it to the proxy. brake session runs any
agent inside its own budget.
Bring your own key, always. Responses are never cached to cut billing. Only request metadata is stored, never bodies or query strings. Every request reaches the provider with your key.
brake estimate prices your last 30 days of Google usage on Geoapify,
Stadia Maps, Open Places API, Mapbox and HERE side by side, and shows what would
stay on Google.
For AI agents
Run any agent or script inside a session with its own cap. When the money runs out, the agent gets one line telling it to stop and ask you, not a quietly growing bill.
brake maps geocode,
brake maps search or
brake call <provider> <method> <path>, each
printing the cost.
$ export BRAKE_KEY=sb_live_… BRAKE_URL=https://proxy.spendbrake.dev $ brake session --budget 5 --day-budget 20 --agent claude -- claude # inside the agent $ brake maps geocode "Vitosha Blvd 1, Sofia" --pretty HTTP 200 · cost $0.0050 · remaining $4.99 { "results": [ … ] } … the agent keeps going … brake: STOP. Spend cap reached for sess:s_7f3a (cap $5.00). Do not retry; ask the user to raise the cap. exit 3
Compared with Google's own controls
Keep Google's budgets and quotas on as a backstop. Spend Brake is the part that acts before the money is spent.
| Google Cloud budgets | Maps Platform quotas | Spend Brake | |
|---|---|---|---|
| Stops spend | No, alerts only | Yes | Yes, before the request leaves |
| Unit | Dollars | Requests per API per minute or day | Dollars, micro-dollar exact |
| Knows SKU tiers (field masks) | After billing | No: a $0.04 request counts like a free one | Yes, priced per field mask |
| Delay | Hours (billing data) | Real time | Real time |
| Granularity | Project / billing account | Project, per API | Org, key, SKU, environment, agent, session; day and month |
| Loop / runaway detection | No | No | Yes, trips a circuit |
| Kill switch | No | Set a quota to 0 by hand | One call, link or button; immediate |
| Alerts with actions | Email, Pub/Sub | No | Webhooks (Slack, Discord, Teams, raw) and email with Kill / Raise / Mute links |
Client-side Maps (the Maps JavaScript API, tiles and widgets) is out of scope: Spend Brake proxies server-side APIs.
Pricing
Every plan enforces caps the same way. Plans differ in how many keys, providers and agent sessions you run, and how long call history is kept.
$0
One project, one provider, a real cap.
$9/month
Side projects and small apps with real traffic.
$49/month
Several services and people, with telemetry you can keep.
$149/month
Fleets of agents, every provider, a year of history.
The core is Apache-2.0 and never needs a license key: proxy, budget engine, caps, kill switch, loop detection, CLI, catalog, dashboard and signed webhooks. Business and Enterprise licenses add single sign-on (OIDC, SAML), more roles, two-person approval for raising caps, audit export, several orgs per install, the signed catalog feed and billing reconciliation. Licenses are checked offline.
$299/month
Self-hosted license, 3 orgs per install.
Prices in USD, before tax. Downgrades and failed payments only block creating new keys, providers and sessions: existing keys and caps keep enforcing.
Self-hosting
One Docker Compose file starts the proxy, admin API, notifier, dashboard, worker, Valkey and Postgres. An HTTPS overlay adds Caddy with automatic certificates; proxy replicas and Valkey Cluster are covered when you outgrow one box.
brake init --api-url … --proxy-url …
$ git clone https://github.com/KIvanow/spend-brake && cd spend-brake $ cp infra/.env.example infra/.env # fill in the secrets $ docker compose -f infra/docker-compose.yml up -d --build --wait $ pnpm install && pnpm --filter @spend-brake/cli build $ node apps/cli/dist/brake.cjs init --api-url http://localhost:8081 \ --proxy-url http://localhost:8080 --org acme --day-cap 5 --month-cap 50 Org acme is ready. An admin token is saved to ~/.config/brake/config.json. Your virtual key (shown once, store it now): sb_live_… Use it instead of the Google key, with the proxy as the base URL: http://localhost:8080/google-maps/maps/api/geocode/json?address=Sofia&key=sb_live_… … then the Google Cloud steps to restrict the real key to the proxy.
Restrict each provider key to the proxy's outbound IP addresses and the APIs you use;
brake init prints the exact steps. Keep the provider's own budgets and
quotas on as a backstop. Overshoot is bounded by one request's worst case, and your
provider's bill remains the authoritative record of what you spent.
Get started
Create a free account, add a provider key, set a cap and make the first call from the Get started page.