Models
The naturali model catalog — what the platform can serve, and what it costs.
Overview
The catalog lists every model naturali offers, with capability metadata,
lifecycle status and the price. It is synced daily, so it reflects what is
available today rather than a snapshot: new models appear on their own, retired
models flip to deprecated, and pricing stays current. Most models are synced
from the provider's own listing and published prices; a provider without a
reliable listing or price API (Vertex) is instead synced from a curated set
naturali maintains, so a listed model is one naturali has verified it can serve.
Where a provider lists a model but publishes no price for it — the Anthropic
models on Bedrock — the listing is still live and only the price is curated, on
the same rule: naturali verifies it can serve the model before offering it — by
generating on it through this API, which is why a model the provider lists is
not always one this catalog carries.
Create an
AI provider with provider: "naturali" in a project and
the models in this catalog from its default_model's source are available to
it (one provider per source — see the naturali provider). No credentials of yours are
involved; that provider runs on naturali's own model access and its usage is
metered at the catalog's pricing.
A model's model is the only string this API asks you for — the same value
goes in a provider's default_model and in an Agent's model.
Enable naturali models
reads it, with its pricing, off the listing.
A model naturali cannot price, one that produces something other than text
(embeddings, images, audio), or one that takes no text input (speech-only), is
not listed here — the runtime's usage meter
is token-based, so naturali cannot meter those truthfully and does not offer
them. To generate on one, register your own credentials as an
AI provider and ask that provider what it serves with
GET /v1/projects/{project_id}/ai-providers/{ai_provider_id}/models,
which answers for your credential rather than for naturali's. That is the path
Knowledge and Embeddings take today: an
embedding model is BYOK-only.
The catalog itself is read-only — there is no create/update/delete, only listing and lookup.
See the OpenAPI spec for the full endpoint and schema reference, or browse it rendered under API Reference → Models.
Data Model
Model
| Field | Type | Description |
|---|---|---|
model | string | The model's name — the only model string this API accepts or returns. Use it verbatim as a provider's default_model and as an Agent's model. |
vendor | string | The model maker (e.g. amazon, meta). |
input_modalities | string[] | Modalities the model accepts as input. |
output_modalities | string[] | Modalities the model can produce. |
streaming | boolean | Whether the model supports streaming responses. |
status | string | available or deprecated, from the provider's listing at the last sync. |
pricing | object | naturali's price, USD per 1K tokens. Always present. |
synced_at | string (date-time) | When the catalog last confirmed this entry against the provider. |
Pricing
| Field | Type | Description |
|---|---|---|
currency | string | Always usd. |
input_per_1k_tokens | number | USD per 1K input (uncached) tokens. |
output_per_1k_tokens | number | USD per 1K output tokens. |
cached_input_per_1k_tokens | number | null | USD per 1K cache-read input tokens; null when the model does not price caching (cached tokens are then billed at the input rate). |
Key Concepts
One model, one name
model is naturali's own name for the model, not the vendor's. It states a
version explicitly (nova-lite-v1, deepseek-v3.2, gemini-3.7-flash) and it
never changes — a vendor relabelling its model cannot move a name your
agents already use.
The vendor's own invocation string is deliberately not published. It would be a
second string that also works, and a model with two names is a model whose
identity you have to keep translating: which one goes in the agent, which one
shows up in a trace, which one your teammate pasted. Sending one where a model
is expected is a 400, not a silent success.
That is also why the catalog does not tell you which cloud serves a model. You chose naturali; which vendor runs it, in which region, through which invocation mode, is naturali's problem — and it can change without your configuration changing.
A retired model stays in the catalog
status is the lifecycle axis and it is independent of the offering. A model
the provider stops listing — or reports as legacy — flips to deprecated and
stays listed, because a project already generating on it needs to see what
happened to it. What changes is that a deprecated model can no longer be
chosen as the default_model of a newly enabled provider.
Filter on it to see only what is current:
- CLI
- SDK
- curl
naturali list-models --status available --vendor amazon
const { data } = await naturali.models.listModels({
query: { status: 'available', vendor: 'amazon' },
});
curl -G https://api.naturali.ai/v1/models \
-H "Authorization: Bearer $NATURALI_TOKEN" \
-d status=available -d vendor=amazon
Enabling naturali models
There is no route on this module that enables anything. The offering is turned
on the same way any other vendor is: create an
AI provider with provider: "naturali" and a
default_model from this catalog.
Enable naturali models does it and
checks the price book the provider gets.
- CLI
- SDK
- curl
naturali create-ai-provider --project-id proj_V1StGXR8Z5jdHi6B \
--name oneclick-ai-provider \
--provider naturali \
--default-model nova-lite-v1
const { data } = await naturali.aiProviders.createAiProvider({
path: { project_id: 'proj_V1StGXR8Z5jdHi6B' },
body: {
name: 'oneclick-ai-provider',
provider: 'naturali',
default_model: 'nova-lite-v1',
},
});
curl -X POST \
"https://api.naturali.ai/v1/projects/proj_V1StGXR8Z5jdHi6B/ai-providers" \
-H "Authorization: Bearer $NATURALI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "oneclick-ai-provider",
"provider": "naturali",
"default_model": "nova-lite-v1"
}'
The provider is priced for the whole catalog before the call returns, and models
that join the catalog later are priced onto it automatically — so this is a
one-time act per project, not one per model. To generate on any other entry, set
the agent's model to that entry's catalog model and point its
ai_provider_id at this provider; no further enabling is involved.
Which vendor serves a model is derived from default_model, never asked
for: the catalog already records it. That is why the naturali slug replaced the
POST /v1/projects/{project_id}/models/providers route this section used to
document — it asked you to know which cloud runs the model you picked, and it
made the same provider reachable two ways.
A provider can only run the models its own vendor offers, so the
default_model you name decides which of the catalog's models this provider can
serve. A project that wants models from more than one vendor creates more than
one naturali provider — each with a default_model from that vendor's set —
and points each agent at the right one. Each is priced only for the models it
can actually serve.
If the catalog has not finished its first sync, the create answers 503
catalog_not_ready rather than provisioning a provider with nothing to serve.
See AI providers for the full create and its refusals.
Pricing follows the provider
pricing is naturali's price for generating on the model, per 1K tokens, and
the daily sync keeps it aligned with the
provider's published price — on the catalog and on providers you have
already enabled, whose metering picks up the new price from the moment it takes
effect. Prices already metered are never rewritten: a usage receipt shows the
price that was in force when the generation ran.
BYOK usage carries no naturali LLM price at all (pricing: null does not
mean free — it means your own provider bills you directly).
Reasoning tokens are output tokens
A model that reasons ("thinks") before answering charges you for the thinking.
Those tokens are counted in output_tokens and billed at
output_per_1k_tokens — there is no separate reasoning rate, and no way to opt
out of paying for them on a model that reasons by default.
They can dominate a small request. One measured generation on
gemini-3-flash-preview, prompted Reply with exactly one word: hello and
answering Hello, spent 13 input tokens and 119 output tokens — 118 of the
119 were reasoning:
{
"key": "gemini-3-flash-preview",
"cost_usd": 0.0003635,
"input_tokens": 13,
"output_tokens": 119,
"components": [
{ "component": "input_tokens", "quantity": 13, "cost_usd": 0.0000065 },
{ "component": "output_tokens", "quantity": 119, "cost_usd": 0.000357 },
{ "component": "reasoning_tokens", "quantity": 118, "cost_usd": null }
]
}
The reasoning_tokens component reports the quantity for visibility; its
cost_usd is null because output_tokens already prices it, not because it
was free. Reading the catalog rate alone and sizing that reply at one or two
output tokens would have under-estimated it by around 100x.
Two things follow. Sizing a workload from the rates needs an output estimate
that includes thinking — for a short answer on a reasoning model that is tens
to hundreds of tokens, not the length of the answer. And a tokens or
cost_usd quota sized the same way is consumed just as fast: the
cap is enforced correctly, against usage larger than the estimate behind it.
Cap a project's spend
sizes one from measured usage instead.
The catalog does not currently carry a per-model flag for this — whether a model
reasons, and how much, is behaviour rather than a published price dimension.
Measure it for your own prompts with
GET /v1/projects/{project_id}/usage,
which breaks a bucket down into the components above.
A catalog entry is not a region guarantee
The catalog answers what naturali serves, not where your own credential can
reach it. Through a naturali-managed provider the two are the same — naturali
runs these models in a configuration it has verified. Through a provider of your
own they can differ: a model is served in some regions and not others, so a
provider pinned to a regional config.location can get a 404 for a model this
catalog lists.
Vertex is where this bites today. The Gemini 3 models are served in the
global location only, so a provider of your own configured for a specific
region cannot reach them. Set config.location to global for those, or ask
the provider record itself with
GET /v1/projects/{project_id}/ai-providers/{ai_provider_id}/models,
which answers with that record's own credential and configuration.
Deprecation keeps history
A model the provider stops listing — or reports as legacy or deprecated —
flips to status: "deprecated" at the next sync and stays in the catalog, so
a project already generating on it can see what happened to it. A deprecated
model cannot be the default_model of a newly enabled provider; a provider
already running one keeps working for as long as the upstream provider still
serves the model.
Examples
List the whole catalog:
- CLI
- SDK
- curl
naturali list-models
const { data } = await naturali.models.listModels();
curl https://api.naturali.ai/v1/models \
-H "Authorization: Bearer $NATURALI_TOKEN"
Look one model up, price included:
- CLI
- SDK
- curl
naturali get-model --model nova-lite-v1
const { data } = await naturali.models.getModel({
path: { model: 'nova-lite-v1' },
});
curl https://api.naturali.ai/v1/models/nova-lite-v1 \
-H "Authorization: Bearer $NATURALI_TOKEN"