Lewati ke konten
kenari.

Pemakaian

Baca pemakaian dan biaya akunmu dari skrip atau agen: total per model, deret per hari, atau log tiap request. Endpoint ini khusus kenari dan tidak punya padanan di OpenAI maupun Anthropic. Angkanya sama dengan halaman Pemakaian di dashboard.

GET /v1/usage
GET /v1/usage/daily
GET /v1/usage/log

Ketiganya membutuhkan API key di header Authorization. Key tanpa pembatasan membaca pemakaian seluruh akun, dari semua API key di akun itu. Lihat Siapa bisa membaca apa.

Ketiga endpoint menerima parameter query dan tidak punya body. Semua parameter opsional. Parameter yang tidak dikenal diabaikan. Kalau parameter diulang, nilai pertama yang dipakai.

ParameterTipeEndpointDeskripsi
startintegersemuaAwal jendela, dalam detik Unix, termasuk batasnya.
endintegersemuaAkhir jendela, dalam detik Unix, termasuk batasnya. Nilai di masa depan dianggap sekarang.
rangestringsemuaJendela preset yang berakhir sekarang: today (sejak 00:00 UTC), 24h, 7d, atau 30d. Default-nya 30d.
modelstringsemuaHanya model dengan id persis ini.
api_key_idstringsemuaHanya request yang dibuat dengan id key ini. Untuk key terbatas, lihat Siapa bisa membaca apa.
billing_kindstring/v1/usage/logHanya jenis penagihan ini: payg, plan, coupon, token_alloc, free, atau byok.
pageinteger/v1/usage/logNomor halaman, dimulai dari 0. Default-nya 0.
limitinteger/v1/usage/logJumlah request per halaman. Default-nya 50. Nilai di luar 1 sampai 200 dipindahkan ke batas terdekat, tidak ditolak.

Ketiga endpoint menentukan jendela dengan cara yang sama.

  • Tanpa start, end, atau range, jendelanya 30 hari terakhir.
  • start dan end menang atas range. Kalau salah satunya ada, range diabaikan, bahkan kalau nilainya tidak valid.
  • Dengan start saja, jendela berakhir sekarang. Dengan end saja, jendela dimulai 30 hari sebelum end.
  • end dibatasi sampai sekarang. start dan end tidak boleh negatif, dan start tidak boleh setelah end.
  • /v1/usage dan /v1/usage/daily menerima jendela yang menyentuh paling banyak 366 hari UTC. Jendela yang lebih panjang menghasilkan 400. /v1/usage/log tidak punya batas itu, tetapi lihat batas kedalaman di bawah.

Response selalu mengulang start dan end yang dipakai, sehingga kamu bisa melihat jendela yang sebenarnya.

billing_kind menunjukkan apa yang membayar sebuah request.

NilaiArti
paygPAYG, dibayar dari saldo.
planDitanggung kuota paket.
couponDitanggung kupon.
token_allocDitanggung alokasi token.
freeModel gratis.
byokDilayani key BYOK milikmu.

Semua jumlah berupa integer dalam mikro-Rupiah, yaitu Rupiah dikali 1.000.000. Rp 1 adalah 1000000. Lihat Cara penagihan. Setiap baris punya dua jumlah.

  • cost_micro_idr adalah jumlah yang dipotong dari saldo kamu. Pemakaian paket, kupon, model gratis, dan BYOK bernilai 0 di sini, karena tidak dibayar dari saldo.
  • catalog_micro_idr adalah nilai pemakaian yang sama menurut harga daftar model. Dengan ini kamu bisa melihat nilai yang kamu dapat dari paket, kupon, model gratis, atau key BYOK, yang tagihannya bisa lebih rendah dari harga daftar atau 0.

GET /v1/usage mengembalikan satu baris per model dan jenis penagihan, diurutkan dari cost_micro_idr terbesar, ditambah baris total. Pemakaian paket dilaporkan sebagai plan. Request tanpa jenis penagihan tercatat dilaporkan sebagai payg.

FieldTipeDeskripsi
objectstringSelalu usage.summary.
startintegerAwal jendela, dalam detik Unix.
endintegerAkhir jendela, dalam detik Unix.
dataarraySatu baris per model dan jenis penagihan. Kosong kalau tidak ada pemakaian.
data[].modelstringId model.
data[].billing_kindstringSalah satu jenis penagihan di atas.
data[].requestsintegerJumlah request.
data[].prompt_tokensintegerToken input.
data[].completion_tokensintegerToken output.
data[].cached_prompt_tokensintegerToken input yang dibaca dari cache.
data[].cache_write_prompt_tokensintegerToken input yang ditulis ke cache.
data[].cost_micro_idrintegerJumlah yang dipotong dari saldo, dalam mikro-Rupiah.
data[].catalog_micro_idrintegerNilai menurut harga daftar, dalam mikro-Rupiah.
totalobjectTujuh penghitung yang sama, dijumlahkan dari semua baris.
{
"object": "usage.summary",
"start": 1788300000,
"end": 1790892000,
"data": [
{
"model": "deepseek-v4-flash",
"billing_kind": "payg",
"requests": 120,
"prompt_tokens": 480000,
"completion_tokens": 96000,
"cached_prompt_tokens": 200000,
"cache_write_prompt_tokens": 0,
"cost_micro_idr": 15400000,
"catalog_micro_idr": 15400000
},
{
"model": "step-3-7-flash:free",
"billing_kind": "free",
"requests": 40,
"prompt_tokens": 52000,
"completion_tokens": 18000,
"cached_prompt_tokens": 0,
"cache_write_prompt_tokens": 0,
"cost_micro_idr": 0,
"catalog_micro_idr": 900000
}
],
"total": {
"requests": 160,
"prompt_tokens": 532000,
"completion_tokens": 114000,
"cached_prompt_tokens": 200000,
"cache_write_prompt_tokens": 0,
"cost_micro_idr": 15400000,
"catalog_micro_idr": 16300000
}
}

GET /v1/usage/daily mengembalikan satu baris per hari UTC di jendela, dari yang terlama. Hari tanpa pemakaian menjadi baris berisi nol, sehingga deretnya tidak berlubang. Filter model dan api_key_id berlaku.

FieldTipeDeskripsi
objectstringSelalu usage.daily.
startintegerAwal jendela, dalam detik Unix.
endintegerAkhir jendela, dalam detik Unix.
dataarraySatu baris per hari UTC.
data[].datestringHari UTC, dalam format YYYY-MM-DD.
data[].requestsintegerJumlah request pada hari itu.
data[].cost_micro_idrintegerJumlah yang dipotong dari saldo pada hari itu, dalam mikro-Rupiah.
{
"object": "usage.daily",
"start": 1790287200,
"end": 1790892000,
"data": [
{ "date": "2026-09-24", "requests": 18, "cost_micro_idr": 2100000 },
{ "date": "2026-09-25", "requests": 0, "cost_micro_idr": 0 },
{ "date": "2026-09-26", "requests": 7, "cost_micro_idr": 950000 }
]
}

GET /v1/usage/log mengembalikan tiap request, dari yang terbaru. Semua filter didukung, termasuk billing_kind. Pemakaian paket dilaporkan sebagai plan.

FieldTipeDeskripsi
objectstringSelalu list.
startintegerAwal jendela, dalam detik Unix.
endintegerAkhir jendela, dalam detik Unix.
dataarrayRequest di halaman ini.
data[].created_atintegerWaktu request dibuat, dalam detik Unix.
data[].modelstringId model.
data[].vendorstringPembuat model.
data[].api_key_idstring atau nullId key yang membuat request. null kalau tidak ada.
data[].billing_kindstringSalah satu jenis penagihan di atas.
data[].prompt_tokensintegerToken input.
data[].completion_tokensintegerToken output.
data[].cached_prompt_tokensintegerToken input yang dibaca dari cache.
data[].cache_write_prompt_tokensintegerToken input yang ditulis ke cache.
data[].cost_micro_idrintegerJumlah yang dipotong dari saldo, dalam mikro-Rupiah.
data[].catalog_micro_idrintegerNilai menurut harga daftar, dalam mikro-Rupiah.
pageintegerNomor halaman yang dipakai.
limitintegerUkuran halaman yang dipakai, setelah dibatasi.
has_morebooleantrue kalau masih ada halaman berikutnya.
totalintegerJumlah request yang cocok dengan filter di seluruh jendela, bukan hanya halaman ini.
{
"object": "list",
"start": 1788300000,
"end": 1790892000,
"data": [
{
"created_at": 1790891000,
"model": "deepseek-v4-flash",
"vendor": "DeepSeek",
"api_key_id": "a1b2c3d4",
"billing_kind": "payg",
"prompt_tokens": 4200,
"completion_tokens": 310,
"cached_prompt_tokens": 2000,
"cache_write_prompt_tokens": 0,
"cost_micro_idr": 128000,
"catalog_micro_idr": 128000
}
],
"page": 0,
"limit": 50,
"has_more": true,
"total": 120
}

page dikali limit tidak boleh lebih dari 10.000. Halaman yang lebih dalam menghasilkan 400. Untuk membaca lebih jauh ke belakang, persempit jendela dengan start dan end, lalu baca per potongan.

  • Key tanpa pembatasan membaca pemakaian seluruh akun, dan bisa mempersempitnya dengan api_key_id.
  • Key dengan batas model, batas pengeluaran, atau batas token adalah key terbatas. Key itu hanya membaca pemakaian key-nya sendiri. Kosongkan api_key_id, atau isi dengan id key itu sendiri. Id lain menghasilkan 400.
  • API key dibagikan tidak bisa membaca pemakaian sama sekali. Hasilnya 403 dan shared_key_not_allowed.

Lihat Autentikasi & API key untuk cara membatasi key.

Ketiga endpoint berbagi satu batas 60 request per menit untuk tiap akun, key mana pun yang dipakai. Kalau melewati batas, request gagal dengan 429 dan rate_limit_exceeded, tanpa header Retry-After. Tunggu beberapa detik lalu coba lagi. Batas ini dihitung terpisah dari batas request chat, jadi membaca pemakaian tidak menghabiskan request chatmu. Lihat Batas laju.

Terminal window
curl "https://kenari.id/v1/usage?range=7d" \
-H "Authorization: Bearer $KENARI_API_KEY"

Deret harian untuk satu jendela, dan log yang difilter ke request PAYG:

Terminal window
curl "https://kenari.id/v1/usage/daily?start=1788300000&end=1790892000" \
-H "Authorization: Bearer $KENARI_API_KEY"
curl "https://kenari.id/v1/usage/log?billing_kind=payg&limit=100&page=0" \
-H "Authorization: Bearer $KENARI_API_KEY"

Skrip ini menjumlahkan pengeluaran bulan ini per model. Skrip membaca ringkasan sejak hari pertama bulan ini dalam UTC, lalu menjumlahkan semua jenis penagihan tiap model.

import os
from collections import defaultdict
from datetime import datetime, timezone
import requests
now = datetime.now(timezone.utc)
month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
response = requests.get(
"https://kenari.id/v1/usage",
headers={"Authorization": f"Bearer {os.environ['KENARI_API_KEY']}"},
params={"start": int(month_start.timestamp())},
)
response.raise_for_status()
usage = response.json()
per_model = defaultdict(int)
for row in usage["data"]:
per_model[row["model"]] += row["cost_micro_idr"]
for model, micro in sorted(per_model.items(), key=lambda item: -item[1]):
print(f"{model}: Rp {micro / 1_000_000:,.0f}")
print("Total:", f"Rp {usage['total']['cost_micro_idr'] / 1_000_000:,.0f}")
const now = new Date();
const monthStart = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1) / 1000;
const response = await fetch(`https://kenari.id/v1/usage?start=${monthStart}`, {
headers: { Authorization: `Bearer ${process.env.KENARI_API_KEY}` },
});
if (!response.ok) throw new Error(await response.text());
const usage = await response.json();
const perModel = {};
for (const row of usage.data) {
perModel[row.model] = (perModel[row.model] ?? 0) + row.cost_micro_idr;
}
for (const [model, micro] of Object.entries(perModel).sort((a, b) => b[1] - a[1])) {
console.log(model, Math.round(micro / 1_000_000));
}

Membaca pemakaian gratis. Lihat Cara penagihan.

StatusKodeKapan
400bad_requestParameter tidak valid: nilai yang bukan integer, start atau end negatif, start setelah end, range yang bukan salah satu dari empat preset (kalau start dan end tidak diisi), jendela lebih dari 366 hari di /v1/usage atau /v1/usage/daily, billing_kind yang bukan salah satu dari enam nilai, page negatif, page dikali limit lebih dari 10.000, atau api_key_id yang bukan id key terbatas itu sendiri. Field param menyebut nama parameternya dan message menjelaskan masalahnya.
401Tidak adaKey tidak ada, tidak valid, atau sudah kedaluwarsa. Body-nya pesan teks singkat, bukan JSON.
403shared_key_not_allowedKey adalah API key dibagikan.
429rate_limit_exceededLebih dari 60 request pemakaian dalam semenit untuk akun. Tidak ada header Retry-After.
500internal_errorPembacaan pemakaian gagal di kenari. Coba lagi sekali.

Body-nya format OpenAI. Pada 400, type berisi invalid_request_error dan param berisi nama parameter. Lihat Error untuk format error dan kode lainnya.