Tài liệu

Tài liệu

API Usage

Truy vấn số lượng token và chi phí của API key đang gửi yêu cầu. Mỗi key chỉ xem dữ liệu của chính nó, không thể truy cập chéo giữa các key. Dùng API này để xây dựng bảng theo dõi thanh toán, đối soát hằng tháng hoặc cảnh báo chi phí của riêng bạn.

GET /v1/usage trả về số liệu tổng hợp về token và chi phí của API key trong header Authorization. Nhóm theo ngày hoặc giờ; tùy chọn tách theo mô hình. Không thể đọc dữ liệu của key khác — hãy đăng nhập vào bảng điều khiển để thực hiện việc đó.

Để xem số dư ví, hãy gọi GET /v1/balance: xem Số dư bên dưới.

Xác thực

Truyền API key Kunavo dưới dạng Bearer token, chính là key có mức sử dụng bạn muốn xem. Endpoint chỉ trả về duy nhất mức sử dụng được tính phí cho key cụ thể này — không có tham số để yêu cầu dữ liệu của key khác.

Coi mỗi key là một dự án riêng. Cách làm được khuyến nghị là tạo một API key riêng cho mỗi ứng dụng được tính phí — bảng điều khiển Kunavo và endpoint này khi đó sẽ tự động tổng hợp theo "từng dự án". Quản lý key tại /app/keys.

Yêu cầu

Tham sốBắt buộcMặc địnhGhi chú
start_dateyes—YYYY-MM-DD, UTC. Tính cả hai đầu. Phải ≤ ngày hôm nay (UTC).
end_dateyes—YYYY-MM-DD, UTC. Bao gồm cả hai đầu. Ngày sau hôm nay được đọc là hôm nay; phản hồi lặp lại end_date đã sử dụng.
bucketnodayMột trong các giá trị day, hour.
group_byno(none)Phân tách bằng dấu phẩy. Được hỗ trợ: model. Bỏ qua để nhận một dòng cho mỗi khoảng thời gian.
Giới hạn khoảng thời gian. bucket=day chấp nhận tối đa 90 ngày; bucket=hour chấp nhận tối đa 7 ngày. Vượt quá giới hạn này, yêu cầu sẽ trả về 400 invalid_request_error — hãy chia thành nhiều lệnh gọi.
Múi giờ. Các khoảng được căn theo ngày/giờ UTC. Nếu cần ngày theo giờ địa phương ở múi giờ khác, hãy truy vấn theo ngày rồi gộp các khoảng biên ở phía client. Tham số tz= trong tương lai sẽ thực hiện việc này phía máy chủ mà không thay đổi trường hiện có nào.

Ví dụ

Tổng theo ngày trong 30 ngày gần nhất, gộp tất cả mô hình:

usage_30d.sh
# Daily totals for the last 30 days
curl https://api.kunavo.com/v1/usage \
  -G \
  -H "Authorization: Bearer $KUNAVO_API_KEY" \
  --data-urlencode "start_date=2026-04-28" \
  --data-urlencode "end_date=2026-05-27"

Một dòng cho mỗi cặp (ngày, mô hình):

usage_by_model.sh
# Per-model daily breakdown — one row per (day, model)
curl https://api.kunavo.com/v1/usage \
  -G \
  -H "Authorization: Bearer $KUNAVO_API_KEY" \
  --data-urlencode "start_date=2026-05-01" \
  --data-urlencode "end_date=2026-05-27" \
  --data-urlencode "group_by=model"

Python — cộng toàn bộ khoảng thời gian thành một số duy nhất:

usage_query.py
import os, datetime as dt, requests

today = dt.date.today()
start = today - dt.timedelta(days=29)  # last 30 days inclusive

r = requests.get(
    "https://api.kunavo.com/v1/usage",
    headers={"Authorization": f"Bearer {os.environ['KUNAVO_API_KEY']}"},
    params={
        "start_date": start.isoformat(),
        "end_date":   today.isoformat(),
        "group_by":   "model",
    },
    timeout=30,
)
r.raise_for_status()
body = r.json()

# body["data"] is one row per (day, model). Sum cost across the window:
total_usd = sum(float(row["cost_usd"]) for row in body["data"])
print(f"Spent ${total_usd:.4f} on key {body['api_key']['name']}")

Phản hồi

200 OK — application/json cùng danh sách các dòng. Các khoảng không có hoạt động sẽ được bỏ qua; client sẽ điền các khoảng trống nếu cần chuỗi liên tục.

response.json
{
  "object": "list",
  "api_key": {
    "id": "k_abc123",
    "name": "production",
    "prefix": "sk-kn-aZ8x"
  },
  "start_date": "2026-05-01",
  "end_date":   "2026-05-27",
  "bucket": "day",
  "data": [
    {
      "bucket_start": "2026-05-01T00:00:00.000Z",
      "model": "claude-sonnet-4-6",
      "requests": 1284,
      "errors": 7,
      "input_tokens": 1532890,
      "output_tokens": 245100,
      "cached_input_tokens": 980000,
      "cache_write_tokens": 12000,
      "web_search_requests": 0,
      "cost_usd": "3.452100"
    },
    {
      "bucket_start": "2026-05-01T00:00:00.000Z",
      "model": "gpt-5",
      "requests": 88,
      "errors": 0,
      "input_tokens": 42000,
      "output_tokens": 12300,
      "cached_input_tokens": 0,
      "cache_write_tokens": 0,
      "web_search_requests": 0,
      "cost_usd": "0.210400"
    }
  ]
}
TrườngLoạiÝ nghĩa
bucket_startchuỗi (ISO 8601, UTC)Thời điểm bắt đầu ngày hoặc giờ được tổng hợp trong dòng này.
modelstringSlug mô hình. Chỉ có khi group_by=model.
requestsnumberSố lệnh gọi thành công trong khoảng này.
errorsnumberSố lệnh gọi kết thúc bằng lỗi/hết thời gian chờ/bị hủy. Không tính phí.
input_tokensnumberTổng số token đầu vào (bao gồm các phần token được lưu trong bộ nhớ đệm và dùng để ghi vào bộ nhớ đệm).
output_tokensnumberTổng số token đầu ra.
cached_input_tokensnumberPhần con của input_tokens được phục vụ từ bộ nhớ đệm prompt của nhà cung cấp thượng nguồn.
cache_write_tokensnumberSố token được ghi vào bộ nhớ đệm trong khoảng này (chỉ Anthropic; các nơi khác là 0).
web_search_requestsnumberCác lượt tìm kiếm trên web phía máy chủ, mỗi lượt được tính phí ngoài token: lượt tìm kiếm của Claude qua /v1/messages và công cụ web_search của OpenAI trên mô hình GPT qua /v1/responses (các trường hợp khác đều là 0).
cost_usdstringSố tiền bạn bị tính phí bằng USD cho khoảng này, chính xác đến 6 chữ số thập phân. Dùng chuỗi để giữ độ chính xác; parseFloat() một cách an toàn.
Lý do chi phí được biểu diễn dưới dạng chuỗi. Chi phí mỗi lệnh gọi rất nhỏ (với lưu lượng dùng nhiều bộ nhớ đệm, chỉ vài phần trăm nghìn của một xu) sẽ bị làm tròn thành 0 theo IEEE-754 nếu chuyển thành chuỗi một cách ngây thơ. Giữ định dạng truyền tải dưới dạng chuỗi với 6 chữ số thập phân giúp mã kế toán của bạn phân tích bằng độ chính xác tùy ý (ví dụ: Decimal()).

Bộ nhớ đệm phía client

Endpoint đặt Cache-Control: private, max-age=60. Hầu hết client (trình duyệt, yêu cầu có phiên, mọi bộ nhớ đệm HTTP phía bạn) sẽ trả về cùng một phản hồi cho cùng tham số trong cửa sổ 60 giây — phù hợp với bảng điều khiển gửi truy vấn định kỳ. Để buộc đọc dữ liệu mới, hãy thay đổi chuỗi truy vấn (ví dụ: thêm một tham số chống bộ nhớ đệm &_=ts) hoặc truyền Cache-Control: no-cache ở phía bạn.

Lỗi

Trạng tháiMãKhi
401authentication_errorThiếu Bearer key, key sai định dạng hoặc đã bị thu hồi.
400invalid_request_errorĐịnh dạng start_date/end_date không hợp lệ, ngày kết thúc trước ngày bắt đầu, start_date sau ngày hôm nay, khoảng thời gian vượt giới hạn của bucket hoặc giá trị group_by không được hỗ trợ.
500internal_errorKhông thể kết nối với DB hoặc xảy ra lỗi ngoài dự kiến.

Điểm cần lưu ý

  • Key đã xóa. Khi bạn thu hồi API key, các dòng sử dụng trong quá khứ của key đó sẽ mất api_key_id (được đặt thành null), vì vậy không thể truy xuất lại tổng số liệu lịch sử qua endpoint này. Dữ liệu vẫn có trong chế độ xem tổng hợp tài khoản trên bảng điều khiển. Nếu cần nhật ký kiểm toán bất biến theo từng key, hãy tải và lưu dữ liệu trước khi thu hồi key.
  • Gần thời gian thực. Các dòng dữ liệu xuất hiện trong vòng vài giây sau khi lệnh gọi tương ứng hoàn tất. Không có giới hạn độ trễ được đảm bảo — nếu cần khớp chính xác với hóa đơn, hãy truy vấn dữ liệu của ngày hôm qua mỗi ngày một lần thay vì truy vấn từng phút.
  • Chi phí là chi phí đã tính phí. Giá trị cost_usd tại đây khớp với số tiền đã trừ khỏi sổ cái ví của bạn. Giá trị này đã phản ánh mức sàn max(catalog, upstream × markup) được mô tả trong Thanh toán. Phản hồi này không có số liệu "giá bán buôn" riêng.

Số dư

GET /v1/balance trả về số tiền mà key thực hiện yêu cầu có thể chi ngay lúc này: số dư ví của tài khoản, số tiền đang được tạm giữ cho các tác vụ vẫn đang chạy và phần còn lại của giới hạn hằng tháng. Lệnh gọi chỉ đọc dữ liệu. Lệnh này không mất phí, không tạm giữ khoản tiền nào và không nhận tham số nào.

balance.sh
curl https://api.kunavo.com/v1/balance \
  -H "Authorization: Bearer $KUNAVO_API_KEY"

Ví dụ về phản hồi:

balance.json
{
  "object": "balance",
  "balance_usd": 12.5,
  "reserved_usd": 3.06,
  "available_usd": 9.44,
  "api_key": {
    "id": "k_abc123",
    "name": "production",
    "prefix": "sk-kn-aZ8x",
    "monthly_limit": {
      "limit_usd": 50,
      "spent_usd": 12.25,
      "remaining_usd": 37.75,
      "resets_at": "2026-11-01T00:00:00.000Z"
    }
  },
  "account": {
    "monthly_cap": null
  },
  "auto_recharge": {
    "status": "off"
  }
}
TrườngLoạiÝ nghĩa
balance_usdnumberSố dư ví của tài khoản. Mọi key thuộc tài khoản đều đọc cùng một số liệu. Khi yêu cầu bị từ chối do số dư quá thấp, phản hồi 402 báo số liệu này trong error.balance_usd.
reserved_usdnumberSố tiền đang được tạm giữ cho các tác vụ hình ảnh, video và âm nhạc của tài khoản vẫn đang chạy. Khoản tiền được tạm giữ cho một tác vụ kể từ khi tác vụ được gửi cho đến khi kết thúc.
available_usdnumberbalance_usd trừ đi reserved_usd, nhưng không bao giờ thấp hơn 0.
api_key.monthly_limitobject|nullGiới hạn chi tiêu hằng tháng được đặt cho key này tại /app/keys, hoặc null nếu key không có giới hạn. Đối tượng có bốn trường: limit_usd, spent_usd (số tiền key đã chi trong tháng dương lịch hiện tại theo giờ UTC, chỉ tính các lệnh gọi thành công), remaining_usd và resets_at.
account.monthly_capobject|nullCùng bốn trường đó, dành cho giới hạn chi tiêu của toàn tài khoản. Giá trị là null, trừ khi Kunavo đã đặt giới hạn cho tài khoản của bạn.
auto_recharge.statusstringCho biết tính năng nạp tiền tự động có nạp tiền vào ví hay không: on, paused (đã bật nhưng dừng lại cho đến khi bạn thao tác tại /app/billing) hoặc off.

Trước khi xử lý yêu cầu, Kunavo tạm giữ một khoản bằng chi phí ước tính của yêu cầu đó. Yêu cầu sẽ bị từ chối với mã 402 nếu khoản ước tính đó vượt quá available_usd hoặc vượt quá remaining_usd của một giới hạn hằng tháng. Khi khoản ước tính vượt quá available_usd và tính năng nạp tiền tự động được bật, Kunavo sẽ nạp tiền vào ví bằng phương thức thanh toán đã lưu nếu balance_usd, chứ không phải available_usd, thấp hơn ngưỡng nạp tiền tự động mà bạn đặt, và lần nạp vẫn nằm trong các giới hạn nạp tiền, rồi thử lại yêu cầu thêm một lần; nếu không có lần nạp nào được thực hiện hoặc số tiền nạp không đủ, yêu cầu sẽ bị từ chối. Yêu cầu vượt quá giới hạn hằng tháng vẫn bị từ chối, dù tính năng nạp tiền tự động có được bật hay không. Khi gần chạm giới hạn, Kunavo đánh giá yêu cầu dựa trên một số liệu có thể cũ tối đa một phút và không tính đến khoản tiền mà các yêu cầu đang chạy tạm giữ, nên một yêu cầu thấp hơn remaining_usd vẫn có thể bị từ chối, một yêu cầu cao hơn có thể được chấp nhận, với phần vượt quá có thể lên tới số tiền đã bị tính phí trong một phút gần nhất, và nhiều yêu cầu chạy cùng lúc có thể cùng nhau vượt quá giới hạn. Với hình ảnh hoặc video, khoản ước tính là giá niêm yết của cấp độ mà yêu cầu sử dụng, nhân với số giây đối với mô hình được tính phí theo giây, và nhân với số hình ảnh khi một yêu cầu hình ảnh cần nhiều hơn một hình (n); GET /v1/models liệt kê giá của từng cấp độ trong trường kunavo.tiers. Với yêu cầu văn bản, khoản ước tính là chi phí đầu vào cộng với chi phí của số token đầu ra tối đa mà giới hạn đầu ra của yêu cầu cho phép (max_tokens; với /v1/chat/completions thì xét max_completion_tokens trước; với /v1/responses thì chỉ xét max_output_tokens), hoặc của 32.000 token đầu ra nếu yêu cầu không đặt giới hạn đầu ra. Số tiền cuối cùng bị tính phí cho yêu cầu có thể khác với khoản ước tính này.

Bản thân khoản tạm giữ không phải là số tiền bị tính phí: khi yêu cầu kết thúc (với tác vụ hình ảnh, video hoặc âm nhạc thì phải đến khi tác vụ kết thúc), Kunavo giải tỏa khoản tạm giữ và trừ chi phí thực tế của yêu cầu vào số dư ví; nếu yêu cầu hoặc tác vụ đó thất bại, Kunavo không trừ gì cả.

Các yêu cầu đang chạy. Khoản tiền tạm giữ cho một yêu cầu đang được trả lời cũng vẫn được giữ cho đến khi yêu cầu kết thúc, và reserved_usd không bao gồm khoản tiền đó. Vì vậy, nhiều yêu cầu được gửi cùng lúc vẫn có thể bị từ chối ngay cả khi từng yêu cầu riêng lẻ đều nằm trong available_usd.

Các khoản tiền được biểu thị bằng đô la Mỹ dưới dạng số JSON, với tối đa sáu chữ số thập phân, theo cùng định dạng như balance_usd và needed_usd trong phản hồi 402. Phản hồi có Cache-Control: private, no-store, và số dư ví cùng các khoản đã tạm giữ được đọc lại ở mỗi lệnh gọi. spent_usd có thể chậm hơn thực tế tối đa một phút.

Key đã dùng hết giới hạn hằng tháng vẫn có thể gọi endpoint này; endpoint không bao giờ trả về 402.

Tiếp theo nên xem gì