Skip to content
kenari.

Models and pricing

List every model you can call, with what it can do and what it costs. The list is public, so you do not need an API key, and it changes over time, so read it from the endpoint instead of hardcoding ids.

GET /v1/models

ParameterTypeRequiredDescription
modalitystringNoList one specialized kind of model instead of the default list. One of embedding, rerank, moderation or systemone. See Filter by modality.

Without modality, the list holds chat, image, text to speech, transcription, music and video models. It does not hold embedding, rerank, moderation or System One models. Each entry’s endpoints says which API it serves, so a tool that only wants chat models should keep the entries whose endpoints include chat. Music models are in the default list too, and there is no ?modality=music filter. The kenari/auto entry, when listed, has no endpoints, because the model that serves a request differs each time. A missing endpoints means no metadata is recorded, not that the model lacks a capability, so the examples below treat it as an empty list.

The response is an OpenAI-style list: {"object": "list", "data": [...]}. This is one entry:

{
"id": "step-3-7-flash",
"object": "model",
"owned_by": "stepfun",
"name": "step-3-7-flash",
"context_length": 262144,
"max_output_tokens": 65536,
"modalities": { "input": ["text", "image", "video"], "output": ["text"] },
"endpoints": ["chat"],
"protocols": ["openai-chat", "openai-responses", "anthropic-messages"],
"reasoning": true,
"reasoning_options": ["low", "medium", "high"],
"reasoning_toggle": false,
"tool_call": true,
"pricing": {
"input": 4200000000,
"output": 24000000000,
"cache_read": 840000000,
"cache_write": null,
"free": false,
"currency": "IDR",
"unit": "micro_idr_per_1m_tokens"
},
"pricing_lines": [
{ "endpoint": "chat", "billable": "input", "unit": "token_1m", "variant": null, "micro_idr": 4200000000 },
{ "endpoint": "chat", "billable": "output", "unit": "token_1m", "variant": null, "micro_idr": 24000000000 },
{ "endpoint": "chat", "billable": "cache_read", "unit": "token_1m", "variant": null, "micro_idr": 840000000 }
],
"sunset_at": null
}

A field kenari has no value for is left out instead of being set to null. id, object, owned_by, name and sunset_at are always there. The rest depends on the kind of entry, as the tables below show.

FieldTypeDescription
idstringThe id to send as model.
objectstringAlways model.
owned_bystringThe vendor that makes the model, for example anthropic.
namestringA display name. Every entry has one. When a model has no separate display name, name is the same as id.
context_lengthintegerThe context window in tokens.
max_output_tokensintegerThe longest output the model can produce in one response, in tokens. Left out when unknown, which means nothing is recorded, not that the model has no limit. Not on ?modality= entries.
modalitiesobjectinput and output arrays. The values are text, image, pdf, file, audio and video. pdf means the model reads PDFs itself. Every chat model lists file, because kenari reads attached documents for any model. Only the native engine depends on the model reading files itself. See Images and files as input.
endpointsarrayThe APIs the model serves: chat, images, videos, audio_speech, audio_transcription, music, embeddings, rerank, moderations or systemone.
protocolsarrayThe API formats you can call the model with: openai-chat for Chat completions, openai-responses for Responses and anthropic-messages for Messages. Only on chat models and kenari/auto, and every one of them lists all three. Left out on image, speech, video, music and ?modality= entries.
reasoningbooleanWhether the model produces reasoning. See Reasoning.
reasoning_optionsarrayThe levels reasoning_effort accepts for this model, such as low, medium and high.
reasoning_togglebooleanPresent on entries of the default list, but not on ?modality= entries. true when you can switch reasoning on or off per request, false when you cannot.
tool_callbooleanWhether the model supports function calling. See Function calling.
pricingobjectThe price card. See Prices in the list.
pricing_linesarrayOne entry per billable item. Left out when the model has none, as on most :free models.
sunset_atinteger or nullThe time, in epoch seconds, when kenari plans to stop serving the model. null when none is planned.
modalitystringOnly on ?modality= results. The kind of model.

Most media fields below are left out when no value is recorded for the model. A missing field means nothing is recorded, not that the model has no limit.

FieldApplies toDescription
voicestext to speechVoice names, case sensitive. The first one is the default when a request has no voice.
formatstext to speechAudio formats the model can return, such as mp3. The first one is the default when a request has no response_format.
max_input_charstext to speechThe longest input the model accepts, in characters. A longer one returns 400.
max_prompt_charsmusicThe longest prompt, in characters.
max_lyrics_charsmusicThe longest lyrics, in characters.
max_duration_secsmusicThe longest song the model makes, in seconds. For information only, because you cannot request a length.
video_durationsvideoThe clip lengths you can request, in seconds.
video_resolutionsvideoThe resolutions you can request, such as 720p.
video_extensionsvideotrue when the model can extend a clip through POST /v1/videos/extensions. Present only when true, and left out otherwise.

For how to use these values, see Text to speech, Music and Videos.

pricing and pricing_lines give prices in micro-Rupiah, which is Rupiah times 1,000,000. Divide by 1,000,000 to get Rupiah. In the example above, an input of 4200000000 is Rp 4,200 per 1 million tokens.

pricing fieldDescription
input, output, cache_read, cache_writeThe price per 1 million tokens. null when the model has no such price.
freetrue when the model costs nothing to call. Prices that are still shown on a free model are the list price of its paid version, and are not charged.
currency, unitAlways IDR and micro_idr_per_1m_tokens.

Models that are not priced per token, such as image, speech and video models, show 0 for input and output. Read their price from pricing_lines instead. Each line has these fields:

FieldDescription
endpointThe API the price belongs to, such as chat or audio_speech.
billableWhat is billed: input, output, cache_read, cache_write, input_audio, output_audio, output_image or output_video.
unittoken_1m for 1 million tokens, 1k_chars for 1,000 characters, second, image or song (music).
variantA tier of the price, such as a video resolution like 720p. null when there is none.
micro_idrThe price in micro-Rupiah for one unit.

A model with a sunset_at keeps being listed and served until that time. After it passes, the model leaves the list and requests for its id are rejected. If you keep a copy of the list, check this field so you can move to another model before the date.

Embedding, rerank, moderation and System One models are listed only when you ask for them with ?modality=.

modalityListsExample idsUsed by
embeddingEmbedding modelsbge-m3, text-embedding-3-smallEmbeddings
rerankRerank modelsbge-reranker-baseRerank
moderationModeration modelsids from this callModerations
systemoneSystem One modelsjev-1-13-freeSystem One
Terminal window
curl "https://kenari.id/v1/models?modality=embedding"

The entries carry id, object, owned_by, name, sunset_at, modality and pricing, and endpoints, context_length and pricing_lines when recorded. They have no reasoning_toggle, and pricing has only input, free, currency and unit, with pricing.input holding the price per 1 million tokens. A modality value that is not one of the four, including an empty one, returns 400.

{
"error": {
"message": "unknown modality 'foo'. Accepted values: embedding, rerank, moderation, systemone.",
"type": "bad_request",
"param": null,
"code": "bad_request"
}
}

A model’s free version has the same id with a :free suffix, is listed with pricing.free set to true, and costs nothing. See Free models.

Terminal window
curl https://kenari.id/v1/models
import requests
models = requests.get("https://kenari.id/v1/models").json()["data"]
chat_models = [m["id"] for m in models if "chat" in m.get("endpoints", [])]
print(chat_models)
const response = await fetch("https://kenari.id/v1/models");
const { data } = await response.json();
const chatModels = data.filter((m) => (m.endpoints ?? []).includes("chat")).map((m) => m.id);
console.log(chatModels);

GET /api/public/pricing is a second public feed, made for price pages. It needs no key and returns {"items": [...], "usd_idr_rate": ..., "free_tier": {...}}.

  • Each item has model, provider (the vendor), free, subscriber_only, endpoints, pricing_lines, input_modalities, output_modalities, sunset_at and upcoming_price, the next scheduled price change, or null when there is none.
  • The per-token prices are named price_in_micro_idr_per_1m, price_out_micro_idr_per_1m, price_cached_micro_idr_per_1m and price_cache_write_micro_idr_per_1m, and image_micro_idr_per_image is the price of one image. market_in_micro_idr_per_1m and market_out_micro_idr_per_1m hold a reference market price, only when kenari’s price is lower.
  • subscriber_only is true when only accounts with an active subscription can call the model. See Subscriptions.
  • It lists every model that is for sale, including the :free versions and older versions of a family. It leaves out embedding, rerank, moderation and System One models.
  • usd_idr_rate is the exchange rate in use, and free_tier describes what a free account gets. For free-tier limits, read Free models.

To find what you can call and what it costs, use GET /v1/models.

StatusCodeWhen
400bad_requestmodality is not embedding, rerank, moderation or systemone.

The other errors are in Errors.

The table below is loaded live from GET /v1/models, so it shows what is billed today. Token prices are in Rupiah per 1 million tokens. Image, speech, video and the other models that are not priced per token have their own tables underneath, each with its unit. For how a request is billed, see How billing works.

Live model pricing

Loading prices...