Skip to main content

Get spend alerts

Proxium sends an alert to the channel that your team reads: Slack, Discord, Telegram or a webhook. An alert tells you about spend, about a model or a vendor that your project retired, or about a data protection match. It never refuses a call. To stop an app at a limit, set a limit. See Set budgets and limits.

What Proxium sends an alert about​

AlertWhenHow often
Spend levelThe spend of the project, or of one app, passes a dollar level that you set, in a day or in a monthOne time for each level, app and day or month
Limit of a key or an appA key or an app nears or reaches one of its limits. You set the limits on Keys and Overview. See Change the percentagesOne time for each percentage, kind of limit and window, for the whole project
Model or vendor retiredYour failover policy retires a model or a vendor. On by default; you turn it off in Routing › When a call failsOne time for each retirement
Data protection matchA class of Data protection set to flag matches a request, or a class set to redact or block with Alert selectedAt most one time in a short window for each class and app, with the number of matches

The day and the month are UTC calendar periods. An app is the value that it sends in the x-proxium-source header.

1. Add a channel​

Open Settings › Spend alerts, and set one or more channels:

ChannelWhat to pasteWhere you get it
SlackThe incoming webhook URL, https://hooks.slack.com/services/…Create a Slack app with Incoming Webhooks for the channel. See Sending messages using incoming webhooks
DiscordThe channel webhook URL, https://discord.com/api/webhooks/…In Discord, open the channel settings › Integrations › Webhooks › New Webhook › Copy Webhook URL
TelegramThe bot token and the chatCreate a bot with @BotFather and copy its token. Add the bot to your group or channel. The chat is the numeric chat id, or @name of a public channel
WebhookAny https URL of yoursProxium sends a POST with a JSON body. See The webhook body

Select Set beside the channel. The console then shows the host of the URL, or bot set for Telegram. It never shows the URL or the token again. Proxium stores them encrypted.

warning

A URL must reach a public address. Proxium refuses a private, loopback or link-local address, because it sends the alert from inside its own network.

2. Send a test alert​

Select Send a test alert. Proxium sends one test message to each channel now. Each channel shows sent, or the reason that it failed. A failed test does not change your settings.

3. Set a spend level​

  1. In Spend levels, leave App empty for the whole project, or type the x-proxium-source value of one app.
  2. In In, select a day or a month.
  3. Type the level in Level, in dollars, for example 20.
  4. Select Add level.

The level shows in the list. Proxium checks the spend often. When the spend passes the level, each channel gets one message, for example:

proxium: app 'support-bot' of project 'acme' spent <amount> today (UTC), over its alert level of <level>

To change a level, add it again with the new amount. A new amount sends a new alert in the same day or month. To remove a level, select Remove.

Change the percentages​

The alerts about the limits of a key or an app come at set percentages of the limit. To change the percentages:

  1. Open Settings › Spend alerts.
  2. In Warn at, type the percentages, separated by commas.
  3. Select Save thresholds.

In force now shows the percentages that apply. To go back to the defaults, select Use the default. To stop all the alerts of the project, select Silence this project.

When a call takes a limit past more than one percentage, you get one alert, for the highest percentage.

note

An alert only sends a message. It never refuses a call, and it never moves a call to another model. To refuse calls at a limit, set the limit itself. See Set budgets and limits.

Check what went out​

Settings › Alerts that went out lists each message: when, what it was about, the channel and its host, and sent, failed or blocked. blocked means that the URL failed the address check.

The webhook body​

A webhook gets one JSON object for each alert. A spend level:

Spend level
{
"type": "proxium.spend.watch",
"project": "acme",
"app": "support-bot",
"period": "day",
"spent": 2140000,
"level": 2000000,
"unit": "millicents",
"at": "2026-10-03T14:05:00Z"
}

app is null for a level of the whole project. spent and level are in millicents: thousandths of a cent.

A limit of a key or an app:

Limit of a key or an app
{
"type": "axon.budget.threshold",
"project": "acme",
"scope": "key",
"dimension": "calls",
"threshold_pct": 80,
"value": 800,
"ceiling": 1000,
"unit": "calls",
"at": "2026-10-03T14:05:00Z"
}

scope is key for a limit of a key, and sender for a limit of an app. The body does not name the key or the app. dimension is calls, cost, rpm or tpm, and unit says how value and ceiling are counted.

A retired model:

Model retired
{
"type": "proxium.model.retired",
"project": "acme",
"scope": "model",
"provider": "t.acme.groq",
"model": "example-model",
"cause": "failures",
"failures_in_a_row": 3,
"retired_minutes": 60,
"until": "2026-10-03T15:05:00Z",
"reason": "ModelUnsupported status=410",
"at": "2026-10-03T14:05:00Z"
}

A retired vendor has "type": "proxium.vendor.retired", "scope": "vendor" and "model": null. When your own key had no credits or was rejected, cause is account and failures_in_a_row is null:

Vendor retired
{
"type": "proxium.vendor.retired",
"project": "acme",
"scope": "vendor",
"provider": "t.acme.openai",
"model": null,
"cause": "account",
"failures_in_a_row": null,
"retired_minutes": 60,
"until": "2026-10-03T15:05:00Z",
"reason": "QuotaExhausted status=402",
"at": "2026-10-03T14:05:00Z"
}

A data protection match:

Data protection match
{
"type": "proxium.guardrail.match",
"project": "acme",
"app": "support-bot",
"class": "credit_card",
"action": "redact",
"requests": 3,
"window_minutes": 10,
"at": "2026-10-03T14:05:00Z"
}

requests is the number of matches that this alert covers. The body never holds the value that matched.

A test alert has "type": "proxium.alert.test", the project and the time. No body holds a prompt, an answer, a key or a key prefix.