Model access
Which models an account can run, why, and how to see and change it
n8v rolls new models out account by account. A model behind a rollout flag runs only for accounts that have the flag, and that holds however the work starts: the web and iOS apps, the CLI, the API, MCP, A2A, GitHub, Slack, Telegram and automations.
- Web
- iOS
- CLI
- API
- MCP
- A2A
- GitHub
- Slack
- Telegram
- Automations
The gate
Is every flag the model needs on for this account?
Yes: it runs
No: refused
answered where you asked, and recorded
How it works, layer by layer
- 1
Rollout flags
Each gated model sits behind one or more flags. An account has each flag on or off.
- 2
The gate
One rule, on the server: a model runs when every flag it needs is on. The pickers show what the gate allows.
- 3
Where it holds
Every run start and provider switch, and before the API, MCP, A2A and the CLI accept a request.
- 4
The record
Every change of access and every refusal, with who, where, when, before and after.
1. Rollout flags
Each gated model sits behind one or more flags, called its gates. Haiku 5.5 sits behind haiku55; Opus 5.5 High sits behind opus55 and opus47EffortLevels, and needs both. Models no flag controls, such as Sonnet 5, run for every account.
An account's value of a flag comes from the first of these that is set:
1Its own value
On or off for this account, set by an admin
2The value for everyone
On or off for all accounts
3The default
From the code; early access turns on some flags
Early access (Settings, General, "Enable early access features") turns on some flags by default for the account, such as the Gemini agent and effort levels. An admin's value for everyone, or for the account, still comes first.
2. The gate
One rule decides, on the server: a model runs when every flag it needs is on for the account. The pickers in the apps list what the same rule allows, so a model a picker offers is never refused.
- A name n8v does not know is refused, including a provider's own id such as
claude-opus-5-5. Use n8v's names, such asopus-5.5; the list has them all. - Preferences only shape the pickers. Hiding a model in Settings, Agent never refuses it.
- The model a chat runs when none is named, your default, skips a model your account can no longer use, as the composer does. You can change it on the Subscription limits page. A default you chose in the Slack or Telegram settings is kept as you chose it.
3. Where it holds
| Where work starts | When it is checked | What you see when it is refused |
|---|---|---|
| Chats: web, iOS, GitHub, Slack, Telegram, automations | At the start of every run, and on a switch to another provider | The chat ends with Model not available; one press sends the message again with another model |
| API, MCP, A2A | Before anything starts or is charged | 403 model_not_enabled, with a hint that points to the list |
CLI (n8v create) | Before the task is created | An error that names the model, and points to n8v models |
A refused run never reaches the agent. A message sent through the API without a model runs the chat's last model; if that model's flag was turned off since, the API accepts the message and the chat ends in the refusal.
4. The record
Every change of who may use what is recorded, with who made it, from where, when, the value before and after, and the reason given:
| Change | Recorded as |
|---|---|
| A value for everyone | Who set it on, off or back to the default |
| One account's own value | Who set or removed it, for which account |
| A default changed in code | Once, by n8v, after the deploy that changed it |
| Early access | The account itself, joining or leaving |
| A flag deleted | Who deleted it, and every account's own value that went with it |
| A refused model | Which account, model and surface, and whether it was a dry run |
A change an admin makes over the API or MCP is recorded the same way, as API or MCP, with the request id of the call that made it, so it can be found in the key's own activity too. Asking for the value a gate already has changes nothing and records nothing.
Changes are kept. Refusals are kept for 90 days, at most one a minute for the same account, model and surface.
See the models you can use
Every model n8v runs, in the order the apps list them, with whether your account can use it.
GET /api/v1/models, with any valid key:
curl -sS https://n8v.online/api/v1/models \
-H "Authorization: Bearer $N8V_API_KEY"{
"default": "sonnet-5",
"models": [
{
"id": "sonnet-5",
"name": "Sonnet 5",
"agent": "claudeCode",
"provider": "Claude Code",
"enabled": true,
"needs": null
},
{
"id": "haiku-5.5",
"name": "Haiku 5.5",
"agent": "claudeCode",
"provider": "Claude Code",
"enabled": false,
"needs": null
}
]
}| Field | Meaning |
|---|---|
default | The model a chat runs when no model is sent |
id | What model takes in POST /chats and POST /chats/{id}/messages |
name | The model's name in the apps |
agent | The agent that runs it, as a stable id: claudeCode, codex, gemini, opencode, amp, grok |
provider | The agent's name in the apps, such as Claude Code or OpenAI Codex |
enabled | Whether your account's flags let it run |
needs | What to connect first, or null. "chatgpt": models only a ChatGPT sign-in, or a compatible provider, serves |
The list_models tool, with the chats:read scope. It lists the models your account can use, grouped by agent, and how many more exist; include_disabled lists those too.
Pass an id as `model` to start_chat or send_message. Without one, chats use sonnet-5.
Claude Code: sonnet-5 (Sonnet 5, default), opus-5.5 (Opus 5.5)
OpenAI Codex: gpt-5.5 (GPT-5.5, needs a ChatGPT sign-in)
1 more model is not enabled for this account; include_disabled lists it.n8v models # the models you can use, by provider
n8v models --all # every model, with the ones not enabled for youn8v create --model takes any name the API takes. An unknown name is answered with the one it most likely means.
When a model is refused
The chat ends with a card: Model not available, the model's name, and the way on.
- Send again with the model in your composer sends your message again, exactly as you wrote it. The chat keeps its branch, agent environment and history, and the agent receives the message as if you had sent it with that model. With the provider switch on, a model of another agent continues the chat there, once that agent is connected to your account.
- Change model opens the task's model picker, and the button then names the model you chose. When the composer holds no model you may use, the card offers Choose a model first.
- Details says what was asked for, why it was refused and what happens to your message, with links to this page and to the models you can use.
While it sends, the button reads Sending with the model, and a refusal shows under the buttons. The chat then shows a divider, Sent again with the model and the time; hover it for the model that was refused and, for the API or MCP, where it came from. Sending the refused model again would be refused again, so it is never offered. A name n8v does not know reads Unknown model. A model that a compatible provider does not serve gets the same card, Model not available on this provider, with the provider's own answer under Details.
An admin also gets Open in Model access, which opens the gate the account lacks.
{
"error": {
"code": "model_not_enabled",
"message": "Model \"haiku-5.5\" is not enabled for this account",
"param": "model",
"hint": "GET /api/v1/models lists every model and whether this account can use it."
}
}An unknown name answers 400 invalid_model, with the model it most likely means:
{
"error": {
"code": "invalid_model",
"message": "Unknown model \"claude-opus-5-5\". Did you mean \"opus-5.5\"?",
"param": "model",
"didYouMean": "opus-5.5",
"hint": "GET /api/v1/models lists every model and whether this account can use it."
}
}Over MCP the same answers arrive as tool errors, with the hint naming list_models.
A chat whose model was refused at the start of a run says so in GET /api/v1/chats/{id} (lastError) and MCP's read_chat (last_error):
{
"lastError": {
"code": "model_not_enabled",
"message": "Haiku 5.5 Low is not enabled for this account.",
"model": "haiku-5.5-low",
"retry": "with_another_model"
}
}Send the message again with another model with POST /api/v1/chats/{id}/retry and {"model": "sonnet-5"}, or MCP's retry_chat. See Retry a chat.
Error: Model "haiku-5.5" is not enabled for this account. `n8v models` lists the models you can use.
Error: Unknown model "claude-opus-5-5". Did you mean "opus-5.5"? `n8v models` lists the models you can use.For admins: Model access
Admin, Model access shows every gate with what it opens, exactly who has it, and the week's refusals. A gate whose model sends prompts to an operator that keeps them is marked, with how many accounts could send it their code.
- Open a gate for its value for everyone (default, on or off) and how many accounts that reaches, the models it decides (Show details for each model's id, the other gates it needs and its refusals), the accounts with their own value, and its own history.
- Every change asks first, stating how many accounts have the gate now and after, and who will run each model: a model behind two gates opens only to accounts that have both. A change that takes access away is marked red. Give an optional reason; each change is recorded and can be undone from its notice, which puts back the value it replaced. Choosing the value a gate already has changes and records nothing, and says so.
- Turn on for an account, or, when a gate reaches everyone, Turn off for an account: an account's own value, which wins over the value for everyone.
- Check an account shows its value of every gate and where each comes from: its own value, the value for everyone, the default or early access.
- Activity lists changes to model gates and early access, and every refusal, as they happen; it reads Live while it refreshes itself, and Paused while older entries are open. From a refusal, check the account or turn on the gate it lacked.
The headline numbers filter the list: Restricted shows only gates some accounts lack, Refused, 7 days opens the refusals. Links can open the page ready: ?gate=haiku55 opens a gate, ?account=<id> checks an account, ?q=Haiku searches.
A change applies to the next run at once. An account's open app picks up its own value immediately, and a value for everyone the next time it loads.
For admins: over the API and MCP
Everything on the page can be read and changed with an API key. Create it in Settings, API: admins see a group Model access, admins only with two scopes.
| Scope | Allows |
|---|---|
model-access:read | Every gate, one account's access, and the activity |
model-access:write | A gate's value for everyone, and one account's own value. Each is recorded |
Only an admin can create such a key, and it expires within 90 days. Every call checks that its owner is still an admin and not banned: until then the key reads and changes nothing. No connected app can hold these scopes, so Claude or ChatGPT connected through Settings never can; over MCP they come only with such a key. Only flags that gate a model can be changed this way.
The key's activity in Settings, API lists each call without its answer, since answers name other accounts.
| Call | Does |
|---|---|
GET /api/v1/model-access | Every gate: what it opens, its value for everyone, who has it, last change |
GET /api/v1/model-access/accounts/{account} | One account, by id or email: each gate on or off, and why |
GET /api/v1/model-access/activity | Changes and refusals, newest first. kind, flag, account, scope=all, limit, cursor |
PATCH /api/v1/model-access/gates/{flag} | {"everyone": "on" | "off" | "default", "reason": "..."} |
PATCH /api/v1/model-access/gates/{flag}/accounts/{account} | {"value": "on" | "off" | "none", "reason": "..."} |
curl -sS -X PATCH https://n8v.online/api/v1/model-access/gates/haiku55 \
-H "Authorization: Bearer $N8V_ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"everyone": "on", "reason": "Haiku 5.5 for everyone at launch"}'{ "flag": "haiku55", "everyone": "on", "was": "default", "changed": true }changed is false when the gate already had that value; nothing is recorded then. A key whose owner is not an admin, or is banned, gets 403 admin_only (listed in its activity once a minute), a flag that gates no model 404 unknown_gate, an account n8v does not have 404 account_not_found.
With such a key as the bearer token, n8v's MCP server also offers:
| Tool | Does |
|---|---|
model_access | Every gate; with flag, one gate in full; or with account, its gates and why each is on or off |
access_activity | Changes and refusals, newest first, with the same filters as the API |
set_model_access | flag with everyone, or flag with account and value; reason is recorded |
set_model_access is marked as a change that needs confirming, so assistants ask before they call it. Names, email addresses, reasons and model ids appear in quotes, as people typed them, so an assistant reads them as data, never as instructions.
Questions
Why does the model picker not show a model? It is not open to your account. Settings, Agent says so under the list, and what early access would add, if anything. Otherwise an admin decides.
Why did the API accept a message that the chat then refused? The message named no model, so it runs the chat's last model, and that model's flag was turned off after the chat began.
Does sending a message again change it? No. The message stays as you wrote it. The chat adds a marker that names the model it was sent with, and the agent receives the message unchanged. It carries on the chat as after a typed message: in the same session for a model of the same family, with the history replayed for another family or agent.
Can a provider's own model id get around a gate? No. n8v runs only the models it knows by its own names; any other name is refused.