Messages
Buat pesan dengan format Anthropic Messages, dan perkirakan berapa token input yang dipakai sebuah request. Endpoint ini kompatibel dengan Anthropic API, jadi SDK resmi Anthropic dan Claude Code langsung bisa dipakai setelah base URL diganti.
POST /v1/messages
POST /v1/messages/count_tokens
Pakai https://kenari.id sebagai base URL, tanpa /v1. SDK Anthropic menambahkan /v1/messages sendiri, dan base URL https://kenari.id/v1 menghasilkan /v1/v1/messages yang mengembalikan 405. Untuk pengaturan Claude Code, lihat Claude Code.
Autentikasi dengan x-api-key: kn-... atau Authorization: Bearer kn-.... Lihat Autentikasi & API key.
Request
Section titled “Request”| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
model | string | Ya | Id katalog, id :free, nama rute, atau id byok/. Nilainya sama dengan di Chat completions. |
messages | array | Ya | Percakapan. Lihat Array messages. |
max_tokens | integer | Tidak | Batas atas token yang dihasilkan. Di sini opsional, berbeda dengan Anthropic API. Bawaan 65.536. |
system | string atau array | Tidak | System prompt, berupa string atau array blok {"type": "text", "text": "..."}. Blok teks digabung dengan satu baris kosong, dan jenis blok lain diabaikan. |
stream | boolean | Tidak | Setel true untuk menerima Server-Sent Events. Lihat Streaming. |
temperature | number | Tidak | Temperatur sampling. |
top_p | number | Tidak | Nucleus sampling. |
top_k | integer | Tidak | Ambil sampel dari K token teratas. |
stop_sequences | array | Tidak | String yang menghentikan generasi. |
tools | array | Tidak | Function tool dengan name, description, dan input_schema, serta server tools kenari seperti {"type": "kenari:web_search"}. Lihat Function calling dan Server tools. |
tool_choice | object | Tidak | {"type": "auto"}, {"type": "any"}, {"type": "none"}, atau {"type": "tool", "name": "..."}. |
thinking | object | Tidak | {"type": "enabled", "budget_tokens": 4096} atau {"type": "disabled"}. Lihat Penalaran. |
output_config | object | Tidak | {"effort": "high"} menyetel tingkat penalaran tanpa anggaran token. Lihat Penalaran. |
metadata | object | Tidak | Diterima. |
kenari tidak menafsirkan field lain. Field itu diteruskan apa adanya ke provider bila model dilayani dalam format Anthropic, dan dibuang bila tidak, jadi jangan bergantung padanya.
Array messages
Section titled “Array messages”Setiap pesan punya field role dan content. role adalah user atau assistant. Pesan system juga diterima di dalam array, seperti yang dikirim Claude Code versi terbaru. content berupa string atau array blok.
| Blok | Kegunaan |
|---|---|
text | Teks biasa. |
image | Gambar dari sumber base64 atau url. Lihat Gambar & berkas sebagai input. |
document | PDF dari sumber base64 dibaca di model apa pun, sama seperti part file di chat, dan ditagih sebagai token input. Sumber url hanya sampai ke model yang dilayani lewat API gaya Anthropic dan dibuang tanpa error untuk model lain. Sumber text adalah teks biasa. Lihat Baca dokumen. |
tool_use | Panggilan fungsi yang dibuat model sebelumnya. |
tool_result | Hasil sebuah panggilan. content berupa string atau array blok text dan image. Setel is_error untuk melaporkan kegagalan. |
thinking, redacted_thinking | Penalaran sebelumnya, dikirim kembali tanpa diubah. |
Jenis blok yang tidak dikenal diabaikan. Blok dengan tipe yang dikenali tetapi struktur yang tidak valid mengembalikan HTTP 400.
Prompt caching
Section titled “Prompt caching”Kirim penanda cache_control seperti yang kamu lakukan ke Anthropic. kenari mempertahankannya bila model dilayani dalam format Anthropic. kenari juga menambahkan titik cache sendiri saat menyusun ulang request, jadi cache tidak bergantung pada penandamu. Lihat Prompt caching.
Response
Section titled “Response”Response berupa objek message Anthropic.
{ "id": "4f1c9a2e7b3d5a60", "type": "message", "role": "assistant", "model": "step-3-7-flash:free", "content": [ { "type": "text", "text": "Halo! Ada yang bisa dibantu?" } ], "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 9, "output_tokens": 12 }}| Field | Keterangan |
|---|---|
content | Array blok: text, tool_use, dan thinking bila model bernalar. Lihat Penalaran. |
stop_reason | end_turn, max_tokens, stop_sequence, tool_use, atau refusal. |
stop_sequence | Selalu null. Bila sebuah stop sequence mengakhiri pesan, stop_reason bernilai stop_sequence. |
usage.input_tokens | Token input yang tidak dilayani dari cache dan tidak ditulis ke cache. |
usage.output_tokens | Token output. Token penalaran ditagih sebagai output. |
usage.cache_read_input_tokens | Token input yang dibaca dari cache. Ada bila provider melaporkannya. |
usage.cache_creation_input_tokens | Token input yang ditulis ke cache. Ada bila provider melaporkannya. |
sources | Ada bila server tool kenari mencari di web. Berisi daftar {url, title} untuk tiap sumber. |
Hitung token
Section titled “Hitung token”POST /v1/messages/count_tokens menerima body yang sama dengan /v1/messages dan mengembalikan perkiraan token input.
{ "input_tokens": 41 }Angkanya diperkirakan dari ukuran request, bukan dihitung dengan tokenizer, jadi anggap sebagai pedoman kasar untuk menyesuaikan jendela konteks. Pemanggilan ini butuh key yang valid, tetapi tidak memeriksa model, tidak menjalankannya, dan tidak dikenai biaya. Body yang tidak bisa diurai mengembalikan 400.
curl https://kenari.id/v1/messages/count_tokens \ -H "x-api-key: $KENARI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "step-3-7-flash:free", "messages": [{ "role": "user", "content": "Halo!" }] }'Contoh
Section titled “Contoh”curl https://kenari.id/v1/messages \ -H "x-api-key: $KENARI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "step-3-7-flash:free", "max_tokens": 512, "system": "Kamu menjawab dengan singkat.", "messages": [{ "role": "user", "content": "Halo!" }] }'Python
Section titled “Python”import osimport anthropic
client = anthropic.Anthropic( base_url="https://kenari.id", api_key=os.environ["KENARI_API_KEY"],)
message = client.messages.create( model="step-3-7-flash:free", max_tokens=512, system="Kamu menjawab dengan singkat.", messages=[{"role": "user", "content": "Halo!"}],)print("".join(block.text for block in message.content if block.type == "text"))TypeScript
Section titled “TypeScript”import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ baseURL: "https://kenari.id", apiKey: process.env.KENARI_API_KEY,});
const message = await client.messages.create({ model: "step-3-7-flash:free", max_tokens: 512, system: "Kamu menjawab dengan singkat.", messages: [{ role: "user", content: "Halo!" }],});for (const block of message.content) { if (block.type === "text") console.log(block.text);}Penagihan
Section titled “Penagihan”Setiap pesan ditagih per token sesuai harga Input, Output, Cache read, dan Cache write model tersebut. Model :free tidak dikenai biaya. count_tokens gratis. Lihat Cara penagihan.
Error memakai envelope Anthropic: objek dengan "type": "error" dan objek error yang berisi type dan message. Di sini hanya error yang khusus untuk endpoint ini. Sisanya ada di Error.
| Status | error.type | Kapan |
|---|---|---|
| 400 | invalid_request_error | Body bukan JSON yang valid atau tidak memuat model atau messages. Role, tipe tool_choice, atau blok bertipe dikenali memiliki struktur yang tidak valid. Id byok/ tidak berformat benar. Model bukan model chat, seperti model gambar atau suara. Request lebih panjang dari jendela konteks model. |
| 400 | not_found_error | model tidak ada di katalog dan bukan salah satu rutemu, atau kamu belum menyimpan key untuk provider di id byok/. |
| 403 | permission_error | Model hanya untuk akun dengan langganan aktif. Id byok/ menyebut provider yang key-nya tidak bisa melayani saat ini. API key punya batas pengeluaran yang tidak bisa dipakai untuk request BYOK. |
| 405 | tidak ada | Base URL berakhir dengan /v1, sehingga SDK memanggil /v1/v1/messages. Pakai https://kenari.id. |