DEV Community

Cover image for Cách theo dõi chi phí API OpenAI theo tính năng: Hướng dẫn phân bổ chi phí
Sebastian Petrus
Sebastian Petrus

Posted on • Originally published at apidog.com

Cách theo dõi chi phí API OpenAI theo tính năng: Hướng dẫn phân bổ chi phí

Hóa đơn OpenAI cho biết bạn đã chi 4.237 đô la tháng trước. Nó không cho biết 3.100 đô la đến từ một endpoint tóm tắt chạy quá mức, 700 đô la đến từ một khách hàng chỉ trả 50 đô la/tháng, và 437 đô la đến từ một tính năng không ai dùng. Muốn ra quyết định về giá, hạn mức hoặc roadmap, bạn cần phân bổ chi phí theo từng request.

Thử Apidog ngay hôm nay

Bài viết này hướng dẫn cách triển khai phân bổ chi phí API OpenAI: gắn metadata cho mỗi request, log usage/token/cost, tổng hợp theo feature/route/customer, đặt budget limit theo key, và kiểm thử wrapper bằng Apidog trước khi đưa lên production.

💡 Apidog giúp bạn kiểm thử request ở cấp kịch bản để xác minh wrapper theo dõi chi phí hoạt động đúng trước khi deploy. Bạn có thể phát lại request đã gắn tag, assert schema log và xác thực mỗi call đều mang metadata mà data warehouse cần.

TL;DR

  • Gắn tag mọi OpenAI API call bằng metadata có cấu trúc: feature, route, customer_id, environment.
  • Ghi một JSON log cho mỗi request, gồm token usage và cost_usd.
  • Tính chi phí tại thời điểm ghi log, không tính lại khi query.
  • Tổng hợp dữ liệu trong BigQuery, ClickHouse, Snowflake hoặc Postgres.
  • Đặt budget limit theo project key trong OpenAI dashboard.
  • Cảnh báo bất thường theo giờ từ data warehouse.
  • Kiểm thử wrapper end-to-end bằng Apidog trước khi tin vào dashboard.

Vấn đề: OpenAI dashboard không đủ để phân bổ chi phí

OpenAI billing dashboard cho bạn biết tổng chi tiêu theo ngày và theo model. Nhưng khi chạy LLM trong production, bạn thường cần trả lời các câu hỏi khác:

  • Feature nào đang tiêu nhiều tiền nhất?
  • Endpoint nào tạo spike?
  • Customer nào đang làm giảm gross margin?
  • Chi phí staging/dev có bị trộn vào production không?
  • Background job nào đang chạy quá mức?
  • Một retry có bị tính hai lần không?

Dashboard gốc không có các chiều phân tích như feature, route, customer_id hoặc environment. OpenAI usage API hữu ích cho đối soát tổng hợp, nhưng không thay thế được attribution ở cấp request.

Nếu bạn cần bối cảnh về giá, xem thêm phân tích chi tiết giá GPT-5.5. Với bài toán billing tương tự trong công cụ dev, xem thanh toán sử dụng GitHub Copilot cho các nhóm API. Tài liệu gốc của OpenAI nằm tại OpenAI API reference.

Mô hình dữ liệu phân bổ chi phí

Đơn vị phân tích nên là một event cho mỗi OpenAI request.

Schema tối thiểu:

Cột Kiểu Ví dụ Mục đích
request_id uuid 7a91... Dedup, retry, trace
timestamp timestamptz 2026-05-06T14:23:01Z Time-series query
feature text support-chat Feature gọi LLM
route text /api/v1/chat/answer HTTP route hoặc background job
customer_id text cust_4291 Chi phí theo khách hàng
environment text prod Tách prod/staging/dev
model text gpt-5.5 Tính giá theo model
prompt_tokens int 15234 Token đầu vào
completion_tokens int 812 Token đầu ra
reasoning_tokens int 4500 Token suy luận, tính theo output
cached_tokens int 12000 Token cache, thường rẻ hơn input thường
latency_ms int 2341 Correlate cost với UX
cost_usd numeric 0.045672 Chi phí đã tính tại thời điểm request
prompt_cache_key text system-v3 Theo dõi cache hit
error_code text 429 Debug retry/error

Tính chi phí tại thời điểm ghi log

Đừng chỉ lưu token rồi tính chi phí sau. Giá có thể thay đổi. Hãy lưu cost_usd ngay khi request hoàn tất để dữ liệu lịch sử phản ánh đúng mức giá tại thời điểm đó.

Ví dụ Python:

PRICING = {  # USD per 1M tokens, as of May 2026
    "gpt-5.5":      {"input": 5.00,  "cached": 2.50,  "output": 30.00},
    "gpt-5.5-pro":  {"input": 30.00, "cached": 15.00, "output": 180.00},
    "gpt-5.4":      {"input": 2.50,  "cached": 1.25, "output": 15.00},
    "gpt-5.4-mini": {"input": 0.25,  "cached": 0.125, "output": 2.00},
}

def compute_cost_usd(
    model,
    prompt_tokens,
    cached_tokens,
    completion_tokens,
    reasoning_tokens
):
    rates = PRICING[model]

    uncached_tokens = max(0, prompt_tokens - cached_tokens)

    input_cost = (uncached_tokens * rates["input"]) / 1_000_000
    cache_cost = (cached_tokens * rates["cached"]) / 1_000_000

    # Reasoning tokens are billed as output.
    output_tokens = completion_tokens + reasoning_tokens
    output_cost = (output_tokens * rates["output"]) / 1_000_000

    return round(input_cost + cache_cost + output_cost, 6)
Enter fullscreen mode Exit fullscreen mode

Token suy luận được OpenAI trả về trong:

usage.completion_tokens_details.reasoning_tokens
Enter fullscreen mode Exit fullscreen mode

Chúng phải được cộng vào output cost, không phải input cost. Nếu bỏ qua phần này, bạn sẽ tính thiếu chi phí cho các chế độ reasoning/thinking.

Bọc OpenAI client bằng attribution wrapper

Mọi call đến OpenAI nên đi qua một wrapper duy nhất. Wrapper nhận metadata, gọi API, đọc response.usage, tính chi phí và ghi log có cấu trúc.

import time
import uuid
import json
import logging
from openai import OpenAI

client = OpenAI()
logger = logging.getLogger("llm.cost")

def call_with_attribution(
    *,
    feature,
    route,
    customer_id,
    environment,
    model,
    messages,
    request_id=None,
    **openai_kwargs
):
    request_id = request_id or str(uuid.uuid4())
    started = time.time()
    error_code = None
    response = None

    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            **openai_kwargs
        )
        return response

    except Exception as e:
        error_code = getattr(e, "code", "unknown_error")
        raise

    finally:
        latency_ms = int((time.time() - started) * 1000)

        usage = response.usage if response else None

        prompt_tokens = getattr(usage, "prompt_tokens", 0)
        completion_tokens = getattr(usage, "completion_tokens", 0)

        cached_tokens = (
            getattr(
                getattr(usage, "prompt_tokens_details", None),
                "cached_tokens",
                0
            ) or 0
        )

        reasoning_tokens = (
            getattr(
                getattr(usage, "completion_tokens_details", None),
                "reasoning_tokens",
                0
            ) or 0
        )

        cost_usd = compute_cost_usd(
            model=model,
            prompt_tokens=prompt_tokens,
            cached_tokens=cached_tokens,
            completion_tokens=completion_tokens,
            reasoning_tokens=reasoning_tokens,
        )

        logger.info(json.dumps({
            "event": "openai.request",
            "request_id": request_id,
            "timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
            "feature": feature,
            "route": route,
            "customer_id": customer_id,
            "environment": environment,
            "model": model,
            "prompt_tokens": prompt_tokens,
            "completion_tokens": completion_tokens,
            "reasoning_tokens": reasoning_tokens,
            "cached_tokens": cached_tokens,
            "latency_ms": latency_ms,
            "cost_usd": cost_usd,
            "error_code": error_code,
        }))
Enter fullscreen mode Exit fullscreen mode

Cách dùng:

response = call_with_attribution(
    feature="support-chat",
    route="/api/v1/chat/answer",
    customer_id="cust_4291",
    environment="prod",
    model="gpt-5.5",
    messages=[
        {"role": "system", "content": "Bạn là trợ lý hỗ trợ kỹ thuật."},
        {"role": "user", "content": "Làm sao reset API key?"}
    ],
)
Enter fullscreen mode Exit fullscreen mode

Nguyên tắc triển khai:

  • Không cho phép feature, route, customer_id, environment mặc định là "unknown".
  • Với retry idempotent, truyền lại cùng request_id.
  • Ghi log mọi request, không sampling.
  • Với background job, dùng route dạng cron:nightly-summary hoặc queue:document-indexing.

Với Node.js, pattern tương tự: wrap SDK, nhận metadata, đọc response.usage, tính cost_usd, ghi một JSON event. Nếu hệ thống đã có Kafka, NATS hoặc Pub/Sub, publish event vào bus thay vì stdout.

Đưa log vào data warehouse

Bạn không cần một pipeline riêng cho LLM nếu đã có logging stack.

Có thể dùng:

  • Vector
  • Fluent Bit
  • Logstash
  • OTLP collector
  • Datadog/CloudWatch export
  • Kafka consumer
  • Custom ingestion job

Đích đến có thể là:

  • BigQuery
  • ClickHouse
  • Snowflake
  • Postgres
  • Redshift

Ví dụ query chi phí theo feature:

SELECT
  feature,
  DATE_TRUNC(timestamp, DAY) AS day,
  COUNT(*) AS requests,
  SUM(cost_usd) AS spend_usd,
  SUM(prompt_tokens + completion_tokens + reasoning_tokens) AS total_tokens,
  AVG(latency_ms) AS avg_latency_ms,
  SUM(cached_tokens) / NULLIF(SUM(prompt_tokens), 0) AS cache_hit_rate
FROM openai_events
WHERE environment = 'prod'
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY feature, day
ORDER BY day DESC, spend_usd DESC;
Enter fullscreen mode Exit fullscreen mode

Chi phí theo customer:

SELECT
  customer_id,
  COUNT(*) AS requests,
  SUM(cost_usd) AS spend_usd,
  AVG(cost_usd) AS avg_cost_per_request
FROM openai_events
WHERE environment = 'prod'
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY customer_id
ORDER BY spend_usd DESC
LIMIT 50;
Enter fullscreen mode Exit fullscreen mode

Top route tiêu tiền hôm qua:

SELECT
  route,
  feature,
  COUNT(*) AS requests,
  SUM(cost_usd) AS spend_usd
FROM openai_events
WHERE environment = 'prod'
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 DAY)
GROUP BY route, feature
ORDER BY spend_usd DESC
LIMIT 20;
Enter fullscreen mode Exit fullscreen mode

Kiểm thử wrapper bằng Apidog

Sau khi có wrapper, hãy kiểm thử nó như một contract. Nếu schema log sai, dashboard và alert của bạn sẽ sai âm thầm.

Dùng Apidog để chạy end-to-end test:

  1. Tạo request đến endpoint AI của bạn.
  2. Truyền customer_id, feature hoặc dữ liệu đầu vào có thể xác định được.
  3. Gọi service qua môi trường staging.
  4. Kiểm tra response.
  5. Kiểm tra log side-channel hoặc log endpoint nội bộ.
  6. Assert các field bắt buộc tồn tại:
    • request_id
    • feature
    • route
    • customer_id
    • environment
    • model
    • prompt_tokens
    • completion_tokens
    • cost_usd
  7. Assert giá trị hợp lệ:
    • cost_usd > 0
    • prompt_tokens > 0
    • environment = "staging"
  8. Phát lại request để kiểm tra retry không bị tính trùng nếu dùng cùng request_id.

Ví dụ assertion logic:

pm.test("cost attribution log is valid", function () {
  const log = pm.response.json().debug.cost_event;

  pm.expect(log.feature).to.eql("support-chat");
  pm.expect(log.route).to.eql("/api/v1/chat/answer");
  pm.expect(log.customer_id).to.eql("cust_test_001");

  pm.expect(log.prompt_tokens).to.be.above(0);
  pm.expect(log.cost_usd).to.be.above(0);
});
Enter fullscreen mode Exit fullscreen mode

Để mở rộng kiểm thử API, xem công cụ kiểm thử API cho kỹ sư QA. Nếu bạn muốn áp dụng contract-first cho cả API và cost attribution, xem phát triển API theo hợp đồng trước.

Đặt budget limit và alert

OpenAI project key giúp bạn chia tách một phần chi phí. Hãy tạo key theo môi trường hoặc feature:

  • prod-support-chat
  • prod-summarization
  • prod-agent-workflows
  • staging-all
  • dev-all

Sau đó:

  1. Đặt hard budget limit trong OpenAI dashboard.
  2. Dùng key riêng cho từng service/feature quan trọng.
  3. Không dùng chung key production cho staging.
  4. Thêm alert từ data warehouse để phát hiện spike nhanh hơn dashboard.

Ví dụ alert SQL chạy mỗi 10 phút:

WITH hourly_spend AS (
  SELECT
    feature,
    TIMESTAMP_TRUNC(timestamp, HOUR) AS hour,
    SUM(cost_usd) AS spend_usd
  FROM openai_events
  WHERE environment = 'prod'
    AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
  GROUP BY feature, hour
),

baseline AS (
  SELECT
    feature,
    AVG(spend_usd) AS avg_hourly_spend
  FROM hourly_spend
  WHERE hour < TIMESTAMP_TRUNC(CURRENT_TIMESTAMP(), HOUR)
  GROUP BY feature
),

current_hour AS (
  SELECT
    feature,
    SUM(cost_usd) AS current_spend
  FROM openai_events
  WHERE environment = 'prod'
    AND timestamp >= TIMESTAMP_TRUNC(CURRENT_TIMESTAMP(), HOUR)
  GROUP BY feature
)

SELECT
  c.feature,
  c.current_spend,
  b.avg_hourly_spend
FROM current_hour c
JOIN baseline b USING (feature)
WHERE c.current_spend > b.avg_hourly_spend * 3;
Enter fullscreen mode Exit fullscreen mode

Gửi kết quả đến Slack, PagerDuty hoặc Opsgenie.

Tối ưu chi phí sau khi đã đo đúng

1. Prompt caching

Nếu model hỗ trợ prompt caching, hãy giữ system prompt và context ổn định ở phần đầu prompt, đặt dữ liệu biến đổi ở cuối.

Theo dõi:

SELECT
  feature,
  SUM(cached_tokens) / NULLIF(SUM(prompt_tokens), 0) AS cache_hit_rate
FROM openai_events
WHERE environment = 'prod'
GROUP BY feature
ORDER BY cache_hit_rate ASC;
Enter fullscreen mode Exit fullscreen mode

Xem thêm tài liệu prompt caching của OpenAI.

2. Batch API cho tác vụ offline

Các job không cần response đồng bộ nên dùng Batch API nếu phù hợp:

  • Tóm tắt hàng đêm
  • Eval run
  • Re-index tài liệu
  • Backfill embedding
  • Xử lý lại dữ liệu cũ

Vẫn gắn tag như request thường, thêm batch_job_id để phân bổ chi phí về job nguồn.

3. Điều chỉnh reasoning effort

Nếu feature đang dùng reasoning ở mức cao, hãy đo lại chất lượng và chi phí ở mức thấp hơn.

Ví dụ test matrix:

Feature Effort Quality score Avg cost/request
support-chat low 0.86 0.012
support-chat medium 0.88 0.031
support-chat high 0.89 0.074

Nếu low đạt chất lượng đủ tốt, bạn không cần trả tiền cho high.

Xem thêm cách sử dụng API GPT-5.5.

4. Kiểm soát context window

Prompt dài là nguồn chi phí phổ biến nhất.

Theo dõi token đầu vào theo feature:

SELECT
  feature,
  AVG(prompt_tokens) AS avg_prompt_tokens,
  APPROX_QUANTILES(prompt_tokens, 100)[OFFSET(95)] AS p95_prompt_tokens
FROM openai_events
WHERE environment = 'prod'
GROUP BY feature
ORDER BY p95_prompt_tokens DESC;
Enter fullscreen mode Exit fullscreen mode

Nếu prompt_tokens tăng đều mỗi tuần mà không có thay đổi sản phẩm tương ứng, prompt hoặc RAG retrieval của bạn đang phình ra.

5. Cảnh báo request gần ngưỡng context lớn

Nếu pricing có multiplier cho request vượt ngưỡng token lớn, thêm guardrail trong wrapper:

if prompt_tokens > 250_000:
    logger.warning(json.dumps({
        "event": "openai.large_context_warning",
        "request_id": request_id,
        "feature": feature,
        "route": route,
        "customer_id": customer_id,
        "prompt_tokens": prompt_tokens,
    }))
Enter fullscreen mode Exit fullscreen mode

Xem thêm bài viết về giá GPT-5.5.

6. Giới hạn theo customer

Với B2B SaaS, bạn nên kiểm tra quota trước mỗi LLM call.

Pseudo-code:

def ensure_customer_ai_quota(customer_id):
    monthly_spend = get_monthly_llm_spend(customer_id)
    monthly_limit = get_customer_ai_limit(customer_id)

    if monthly_spend >= monthly_limit:
        raise AiQuotaExceeded(
            "Quota AI hàng tháng đã vượt quá. Vui lòng nâng cấp gói."
        )
Enter fullscreen mode Exit fullscreen mode

Chi phí LLM nên là một phần của unit economics, không phải khoản chi chung không kiểm soát.

Lỗi phổ biến cần tránh

  • Gắn tag ở cấp SDK thay vì tại điểm gọi.
  • Để customer_id = null.
  • Không gắn tag background job.
  • Bỏ qua reasoning_tokens.
  • Tính reasoning_tokens theo input price thay vì output price.
  • Dùng OpenAI dashboard cho alert thời gian thực.
  • Sampling log request.
  • Không dedup retry bằng request_id.
  • Trộn staging/dev vào production.
  • Không cố định bảng giá theo thời điểm request.

Có nên tự xây hay dùng công cụ?

Phương pháp Ưu điểm Chi phí Khi nên dùng
OpenAI usage API Native, không cần setup, khớp billing Miễn phí Một project, ít feature, không cần customer attribution
Helicone Proxy nhanh, dashboard, cache, cost per user Có free tier; trả phí từ khoảng 20 đô la/tháng Muốn dashboard nhanh và chấp nhận proxy
Langfuse Open-source, tracing + cost Self-host miễn phí; cloud từ khoảng 29 đô la/tháng Muốn trace và cost trong cùng hệ thống
LangSmith Tích hợp tốt với LangChain, eval + cost Trả phí từ khoảng 39 đô la/user/tháng Đã dùng LangChain
Custom warehouse Kiểm soát hoàn toàn, không proxy, tích hợp data stack Thời gian kỹ thuật Scale lớn, cần dimension tùy chỉnh, yêu cầu dữ liệu nghiêm ngặt

Tham khảo thêm:

Use case thực tế

SaaS B2B

Một sản phẩm sales intelligence dùng GPT-5.5 để tạo tóm tắt. Trước attribution, công ty chỉ biết tổng chi OpenAI là 80.000 đô la/tháng. Sau khi phân bổ theo customer_id, họ thấy 12% khách hàng tạo ra 71% chi phí.

Hành động:

  • Thêm tier pricing.
  • Đặt soft quota cho gói thấp.
  • Tính overage cho usage cao.
  • Theo dõi gross margin theo customer.

Kết quả: feature AI chuyển từ rủi ro margin thành sản phẩm có thể định giá.

Công cụ nội bộ cho developer

Một tổ chức cấp trợ lý GPT riêng cho developer. Khi dùng customer_id = dev_email, platform team phát hiện 3 developer tạo 50% chi phí. Hai người đang chạy agent loop bị quên tắt. Tắt loop tiết kiệm 1.800 đô la/tháng.

Dự báo chi phí feature mới

Trước khi launch feature tóm tắt, product team dùng dữ liệu lịch sử để ước tính:

cost/user/day =
  avg_calls_per_user_per_day
  * avg_cost_per_call
Enter fullscreen mode Exit fullscreen mode

Nếu kết quả là 0,04 đô la/user/ngày, tức khoảng 1,20 đô la/user/tháng, pricing team có cơ sở để định giá feature ở mức 5 đô la/user/tháng.

Checklist triển khai

  • [ ] Tạo wrapper duy nhất cho OpenAI client.
  • [ ] Bắt buộc truyền feature, route, customer_id, environment.
  • [ ] Đọc response.usage.
  • [ ] Tính cost_usd tại thời điểm request.
  • [ ] Ghi JSON log cho mọi request.
  • [ ] Dedup retry bằng request_id.
  • [ ] Đưa log vào data warehouse.
  • [ ] Tạo dashboard theo feature, route, customer.
  • [ ] Tạo alert spike theo giờ.
  • [ ] Tạo project key theo môi trường/feature.
  • [ ] Đặt budget limit trong OpenAI dashboard.
  • [ ] Kiểm thử wrapper bằng Apidog.

Kết luận

OpenAI billing dashboard trả lời câu hỏi “đã chi bao nhiêu”. Đội sản phẩm và kỹ thuật cần trả lời câu hỏi “chi phí đến từ đâu”.

Cách triển khai thực tế:

  1. Bọc mọi OpenAI call bằng attribution wrapper.
  2. Gắn tag ở điểm gọi.
  3. Ghi usage và cost thành event có cấu trúc.
  4. Tổng hợp trong data warehouse.
  5. Đặt budget limit theo key.
  6. Cảnh báo bất thường theo feature/customer/route.
  7. Kiểm thử schema log bằng Apidog trước khi production.

Tải Apidog và dùng nó để xác minh wrapper phân bổ chi phí từ đầu đến cuối: gửi request đã gắn tag, assert payload log và phát lại kịch bản trên nhiều môi trường.

Đọc thêm:

Câu hỏi thường gặp

Token suy luận được tính là input hay output?

Output. OpenAI trả về token suy luận trong usage.completion_tokens_details.reasoning_tokens. Khi tính chi phí, cộng chúng vào output tokens. Xem thêm phân tích giá GPT-5.5.

response.usage có khớp OpenAI dashboard không?

Token count trong response.usage nên khớp với billing usage. Sai lệch thường đến từ việc bạn dùng bảng giá cũ. Hãy version bảng giá theo ngày hiệu lực.

Chỉ dùng OpenAI project key có đủ không?

Không nếu bạn cần phân bổ theo feature, customer hoặc route. Project key chỉ cho bạn một chiều phân bổ. Metadata cấp ứng dụng vẫn cần thiết.

Retry có làm tính trùng chi phí không?

Có thể. Nếu request thành công rồi app retry, bạn có thể log hai lần. Với retry idempotent, truyền lại cùng request_id và dedup khi ghi hoặc khi ingest.

OpenAI usage API nhanh đến mức nào?

Có độ trễ từ vài chục phút đến vài giờ. Dùng nó cho đối soát, không dùng cho alert thời gian thực.

Có nên sampling log không?

Không. Một JSON line cho mỗi request là rất nhỏ. Sampling làm hỏng phân bổ theo customer và route.

Cách này dùng được cho provider khác không?

Có. Thêm cột provider, ví dụ openai, anthropic, google, deepseek, và bảng giá riêng cho từng provider. Schema và dashboard có thể dùng chung. Xem thêm giá API DeepSeek V4.

Embeddings và image generation thì sao?

Dùng cùng pattern, nhưng công thức cost khác. Thêm cột endpoint, ví dụ chat, embeddings, image, rồi branch logic tính chi phí theo loại endpoint.

Top comments (0)