Enable naturali models
By the end of this tutorial you will have a project that can generate on any naturali-managed model, with no model-vendor account and no credential of your own.
Three steps:
- Create a project — the tenancy boundary everything else lives in.
- See what naturali offers — the catalog of managed models and their prices.
- Enable them — one provider, and every managed model that vendor serves is available.
Then validate it. Every step is one API call, shown for all three clients. The ids in the responses are examples — copy the ones your own calls return.
This tutorial uses naturali's model access, billed at the catalog's price. If you have your own vendor credential and want to use it, do Create a provider instead — the two paths are independent, and a project can use both.
Prerequisites
You need an account-scoped nat_sk_… API key (or
a session JWT from Auth) exported as NATURALI_TOKEN.
That is all — there is no vendor key in this tutorial.
A key is project-scoped by default, and a project-scoped key cannot create a
project: step 1 answers 403 access_denied. With one, skip step 1 and export
the PROJECT it is scoped to.
export NATURALI_TOKEN=nat_sk_...
Then set your client up:
- CLI
- SDK
- curl
pnpm add -g @naturali/cli
The CLI reads NATURALI_TOKEN from the environment. See the
CLI guide.
pnpm add @naturali/sdk
import { NaturaliClient } from '@naturali/sdk';
const naturali = new NaturaliClient({ token: process.env.NATURALI_TOKEN });
See the SDK guide.
Nothing to install — every call sends the credential as a bearer header:
curl https://api.naturali.ai/v1/users/me \
-H "Authorization: Bearer $NATURALI_TOKEN"
1. Create a project
A project is the isolation boundary: providers, agents and everything else belong to exactly one, and your credential is authorized against it per request.
- CLI
- SDK
- curl
naturali create-project --name "getting started"
const { data: project } = await naturali.projects.createProject({
body: { name: 'getting started' },
});
curl -X POST https://api.naturali.ai/v1/projects \
-H "Authorization: Bearer $NATURALI_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "getting started" }'
{
"id": "proj_V1StGXR8Z5jdHi6B",
"name": "getting started",
"role": "owner",
"owner_user_id": "user_V1StGXR8Z5jdHi6B",
"status": "active"
}
You are the project's owner — the role that may do anything in it — and its
billing owner.
export PROJECT=proj_V1StGXR8Z5jdHi6B
2. See what naturali offers
The catalog is the same for every project, and it is synced daily against the provider's own listing and published prices. Everything in it is a model naturali serves for you:
- CLI
- SDK
- curl
naturali list-models --status available
const { data } = await naturali.models.listModels({
query: { status: 'available' },
});
curl -G https://api.naturali.ai/v1/models \
-H "Authorization: Bearer $NATURALI_TOKEN" \
-d status=available
{
"data": [
{
"model": "nova-lite-v1",
"vendor": "amazon",
"input_modalities": ["text", "image", "video"],
"output_modalities": ["text"],
"streaming": true,
"status": "available",
"pricing": {
"currency": "usd",
"input_per_1k_tokens": 0.00006,
"output_per_1k_tokens": 0.00024,
"cached_input_per_1k_tokens": 0.000015
},
"synced_at": "2026-10-03T07:36:20.628Z"
}
],
"next_cursor": "Z3B0LW9zcy1zYWZlZ3VhcmQtMjBi"
}
The listing is paginated: pass next_cursor
back as cursor for the next page until it is null.
Two fields matter later. model
is the string you use everywhere a model is named — a provider's
default_model, an agent's model. pricing
is what generating on it costs, per 1K tokens.
A model naturali cannot price, or one that does not produce text, is not in this catalog. To generate on one of those, bring your own credential via Create a provider.
3. Enable them
Create one provider with
provider: "naturali".
It takes no credential, and it is priced for the whole catalog the moment it
exists.
- CLI
- SDK
- curl
naturali create-ai-provider --project-id "$PROJECT" \
--name naturali \
--provider naturali \
--default-model nova-lite-v1
const { data: provider } = await naturali.aiProviders.createAiProvider({
path: { project_id: process.env.PROJECT! },
body: {
name: 'naturali',
provider: 'naturali',
default_model: 'nova-lite-v1',
},
});
curl -X POST "https://api.naturali.ai/v1/projects/$PROJECT/ai-providers" \
-H "Authorization: Bearer $NATURALI_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "naturali",
"provider": "naturali",
"default_model": "nova-lite-v1"
}'
{
"id": "aip_NzjzJDzoId8cm1Hu",
"project_id": "proj_cT9LACJi0WypPf5U",
"name": "naturali",
"provider": "naturali",
"default_model": "nova-lite-v1",
"created_at": "2026-10-03T08:12:21.660Z"
}
There is no credential on it — that is the whole point. default_model is any
catalog model the listing showed as available: it is what agents that name
no model of their own fall back to, and it is also what tells naturali
which vendor serves this provider,
so you never state that yourself.
export PROVIDER=aip_NzjzJDzoId8cm1Hu
This is a one-time call per project, not one per model. Models that join the catalog later are priced onto this same provider automatically.
The result is an ordinary AI provider from here on — read it, rename it, or delete it through the usual endpoints.
4. Validate it
Ask the provider what it is priced for. Every managed model its vendor serves should appear, which is the proof that all of them are ready to generate and will be metered correctly.
- CLI
- SDK
- curl
naturali get-ai-provider-prices \
--project-id "$PROJECT" \
--ai-provider-id "$PROVIDER"
const { data } = await naturali.aiProviders.getAiProviderPrices({
path: {
project_id: process.env.PROJECT!,
ai_provider_id: process.env.PROVIDER!,
},
});
curl "https://api.naturali.ai/v1/projects/$PROJECT/ai-providers/$PROVIDER/prices" \
-H "Authorization: Bearer $NATURALI_TOKEN"
{
"prices": [
{
"id": "price_msDvPYVtvcwh9lV2",
"ai_provider_id": "aip_NzjzJDzoId8cm1Hu",
"meter_type": "llm_tokens",
"provider": "bedrock",
"model": "nova-lite-v1",
"component": "input_tokens",
"unit": "token",
"unit_price": 6.000000000000001e-8,
"effective_from": "2026-10-03T08:12:21.670Z"
}
]
}
One row per model per priced component (input_tokens, output_tokens, and
cached_tokens where the model prices cache reads), all with the same
provider. Only the catalog models served the way default_model is are priced
here; a model served another way — Gemini, on the run above — takes a second
provider whose default_model is one of them. unit_price is per
token here, where the catalog quotes per 1K — the same number, scaled.
An empty list means the provider was created but not priced; delete it and enable again.
What's next
- Your first agent generation — create an agent
on this provider and run it. Set the agent's
modelto any catalogmodelto use that model instead of the default. - Models — how the catalog stays current, what it covers, and how deprecation is handled.
- Projects → Project usage — the usage meter, where the cost of every generation shows up.