Develop / Guides
Budgets per key
How to give each application its own spending limit, when it resets and how your code responds to status code 402.
A budget limits what an API key may spend in euros. Once it is used up, the gateway rejects further requests from this key with 402. Other keys of your organisation keep working.
-
Create one key per application
Create a separate key for each application and each environment, for example
chatbot-productionandchatbot-test. A budget then affects exactly one application, and the usage per key shows which application causes which costs.Admins of your organisation create keys under Models → API keys with New key.
Result: each application has its own key.
-
Set the budget
When you create the key, or later through Details & edit, enter two values in the Budget section:
- Spending limit (€): the maximum amount, for example €50. Empty means no limit.
- Reset: Never, Daily, Weekly or Monthly.
Reset New period begins Daily every day at 00:00 UTC Weekly on Mondays at 00:00 UTC Monthly on the 1st of the month at 00:00 UTC Never never; the limit applies to the entire lifetime of the key Result: under Models → API keys, the Usage column shows the amount spent in the current period. Once the limit is reached, it shows Limit reached.
-
Handle 402
For status code 402, check the
codefield in the error object:key_budget_exhausted: this key’s budget is used up for the current period.insufficient_credit: the organisation’s credit is not sufficient. Organisations that pay from credit see this error (see Credit & billing).
Do not repeat the request unchanged for
key_budget_exhausted. Once the limit is reached, it fails until the next reset or until an admin raises the limit. If the message names an estimate (see below), a smallermax_tokensmay be enough.Result: your application tells an exhausted budget apart from missing credit.
curl -s https://api.noirdoc.de/v1/chat/completions \ -H "Authorization: Bearer $NOIRDOC_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen3.8-27b", "max_tokens": 500, "messages": [{"role": "user", "content": "Hello"}] }' \ | jq '.error.code'import os import openai from openai import OpenAI client = OpenAI( base_url="https://api.noirdoc.de/v1", api_key=os.environ["NOIRDOC_API_KEY"], ) try: response = client.chat.completions.create( model="qwen3.8-27b", max_tokens=500, messages=[{"role": "user", "content": "Hello"}], ) except openai.APIStatusError as e: if e.status_code != 402: raise code = e.response.json()["error"]["code"] if code == "key_budget_exhausted": ... # pause until the reset elif code == "insufficient_credit": ... # ask admins to top upimport OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://api.noirdoc.de/v1", apiKey: process.env.NOIRDOC_API_KEY, }); try { await client.chat.completions.create({ model: "qwen3.8-27b", max_tokens: 500, messages: [{ role: "user", content: "Hello" }], }); } catch (err) { if (!(err instanceof OpenAI.APIError)) throw err; if (err.status !== 402) throw err; if (err.code === "key_budget_exhausted") { // pause until the reset } else if (err.code === "insufficient_credit") { // ask admins to top up } }
What the budget counts
The budget counts two types of cost:
- Managed models: requests to priced models managed by Noirdoc.
- Noirdoc Shield (€0.40 per 1M inspected input tokens): the flat fee across all five protection filters counts towards the key budget (as well as any request tag budgets) whenever Noirdoc Shield inspects text – on Chat, Responses, Messages, Embeddings and Rerank, on requests blocked with 403
shield_violation, and on the standalone inspection endpointPOST /v1/shield/inspect.
On requests routed through your own provider keys (BYOK), model tokens remain unbilled by Noirdoc. When Noirdoc Shield is active on a BYOK request, however, the Shield inspection fee (€0.40 per 1M input tokens) is billed against your organisation’s credit (or invoice) and counts towards API key and request tag budgets. Without active Shield, BYOK calls remain €0 at Noirdoc. Legacy masking for pre-existing organisations remains €0 until its sunset on 30.11.2026.
The gateway books the cost of a request to the key after inspection or after the response.
Check before the request
Before processing, the gateway estimates the highest possible cost of a request:
- Input: the length of the input fields (such as messages, system prompt, tool definitions) as JSON in characters, divided by 4, as tokens – plus €0.40 per 1M input tokens when Noirdoc Shield is active (including on BYOK routes and on
POST /v1/shield/inspect). - Output: the value from
max_tokens,max_completion_tokensormax_output_tokens. If it is missing, the gateway calculates with 4,096 tokens.
For images, it estimates the number times the price per image or megapixel. If previous usage plus the estimate exceeds the spending limit, the gateway answers with 402 key_budget_exhausted. The message names the estimate and the remaining budget. Set max_tokens to suit your application, so that short requests still go through shortly before the limit.
For audio endpoints, the gateway checks without an estimate whether the limit has already been reached.
{
"error": {
"type": "insufficient_quota",
"code": "key_budget_exhausted",
"message": "This request could cost up to 0.42 EUR, more …",
"param": null
}
}Errors
| Status | Code | Meaning |
|---|---|---|
| 402 | insufficient_credit | The organisation's credit is used up or lower than the estimated maximum cost of the request (including Noirdoc Shield, also on BYOK routes when Shield is active). |
| 402 | key_budget_exhausted | This key's budget is used up for the current period or does not cover the estimated cost of the request. |