Policies & catalog
A key does not see every model Belarel offers. It sees the models your organization is entitled to, narrowed by the choices your organization made and by the key’s own settings. Every call reports which rules let it through — or which rule stopped it — in belarel.policy.decisions.
Which models a key can call
Section titled “Which models a key can call”A model is callable by a key only if it passes every one of these filters:
| Filter | Who sets it |
|---|---|
| The model is exposed to the API and active | Belarel |
| The model is available to your organization | Belarel (some models are offered only to specific customers) |
| The model is served in your organization’s data residency zone | Your organization |
| Your contract allows it: blocked models, allowed models, allowed providers | Your contract |
| Your organization opened it to API keys: all models, a selected list, or none — separately for language and embedding models | Your organization’s dashboard |
The key’s allowed_model_keys, when set |
The key (or its parent, for a sub-key) |
GET /v1/models, called with your key, lists exactly the result: the models that key may call, priced for your organization. Embedding models appear only for a key with the embeddings scope that does not run on BYOK. When the list is empty, belarel.empty_reason names the filter that removed everything: not_exposed, residency, org_api_disabled or org_api_restriction. See Models.
A model you cannot see is a 404
Section titled “A model you cannot see is a 404”A model that does not exist, is not exposed to the API, or is not available to your organization answers 404 model_not_found — the same answer in all three cases. Its belarel.policy.decisions carries only the generic decision {"rule": "unknown_model", "verdict": "deny"}, never the rule that actually applied. Belarel never confirms that a model exists if you cannot use it.
A model your organization can see but has excluded answers 403 model_not_allowed, and names the rule:
| Rule | Why the model is refused |
|---|---|
contract_blocked_models |
Your contract blocks this model. |
contract_allowed_models |
Your contract allows a list of models, and this one is not on it. |
contract_allowed_providers |
Your contract allows a list of providers, and this model’s provider is not on it. |
residency |
The model is not served in your organization’s residency zone. |
org_api_restriction |
Your organization opened a selected list of models to API keys, and this one is not on it. |
org_api_disabled |
Your organization turned off this kind of model for API keys. |
key_allowed_models |
The key’s own model list excludes it. |
A refused call carries the rule next to the error, in the OpenAI error shape your SDK already reads:
{ "error": { "message": "Model \"<model-id>\" is blocked by this organization's contract", "type": "permission_error", "code": "model_not_allowed", "param": "model" }, "belarel": { "request_id": "req_6f1c0a7e2b9d4c3f8e5a1b2c3d4e5f60", "policy": { "decisions": [{ "rule": "contract_blocked_models", "verdict": "deny" }] } }}Two more refusals come from the catalog: 403 model_not_priced (a live key on a model that has no platform price yet — it cannot be served) and 503 admission_unavailable (the catalog could not be read; Belarel refuses rather than guess). An organization that has no price list at all gets 503 pricing_unavailable on its live calls instead — contact support.
Policy decisions on a successful call
Section titled “Policy decisions on a successful call”Every answer’s belarel.policy.decisions lists the rules that applied, in the order they were evaluated. Each entry has a rule, a verdict (allow, deny or warn) and an optional detail.
| Rule | Present when |
|---|---|
org_api_catalog |
Always, for language models; detail names your residency zone. |
embedding_model |
Always, for embeddings; detail names your residency zone. |
contract_blocked_models, contract_allowed_models, contract_allowed_providers |
Your contract sets that list. |
key_allowed_models |
The key restricts its models. |
credential_mode |
The key runs on your organization’s own provider key (BYOK). |
contract_max_cost_per_request |
Your contract sets a cost ceiling per request. |
reasoning_effort |
You asked for a reasoning effort. |
A warn verdict means the call went through, but something you asked for was not applied. Today that happens when you set reasoning_effort on a model whose vendor takes no effort setting: the call runs at the model’s default, and the decision says so.
Sampling parameters follow a related rule. Belarel forwards top_p, stop, seed, presence_penalty, frequency_penalty and tool_choice to the model, and refuses by name, with 400 unsupported_parameter, any field it cannot honour. A model’s provider may still drop a forwarded parameter — some ignore seed, the penalties, or top_p next to temperature. When that happens, the answer lists them in belarel.ignored_parameters, by their OpenAI names. A model’s supported_parameters in GET /v1/models lists what Belarel forwards for it.
Maximum cost per request
Section titled “Maximum cost per request”Your contract can set a ceiling on the cost of a single request. Belarel compares it with the call’s reserved estimate — the worst case, with the full output ceiling — not with what the call would eventually cost. A call over the ceiling is refused before it runs:
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
max_cost_per_request |
402 | The estimate exceeds your contract’s ceiling per request. param names the output limit (max_tokens, or max_output_tokens on Responses; input on Embeddings). |
Lower max_tokens, shorten the prompt, or pick a cheaper model. |
The refusal carries a contract_max_cost_per_request decision with the estimate and the ceiling in detail. Sandbox keys are never checked against it. See Admission & settlement for how the estimate is built.

