LLM API cost allocation and reconciliation: split spend by key, project and group
Allocating LLM API costs by project starts with one key per project. Logs record every call's cost under its key and export to CSV; the Dashboard sums spend by key, group and model. How to split the bill, monthly reconciliation steps, export limits and how to request invoices.
Allocating LLM API costs by project starts with one key per project. Every call's cost is recorded under the key that made it; Logs in the console filter by key, model and group and export to CSV, and the Dashboard sums spend by key, group and model so you can see the structure. At the start of each month, export the previous month's usage and refund records, sum them by the API key column with refunds subtracted to get each project's cost, check the usage total against Spend in period, check top-ups against the top-up records, and archive the CSV. We issue both China domestic invoices (fapiao) and overseas invoices.
Split your keys first
Costs split only as finely as your keys do. Give each project, department or customer its own key and name it after the owner, such as support-bot-prod or marketing-copy. If several projects share a key, the platform cannot tell them apart for you. Splitting keys by member, project and environment is covered in Teams and multiple projects on one account.
Where the data comes from
| Data | Where | Use it for |
|---|---|---|
| The cost of every call | Usage records in Logs, exportable to CSV | The basis for reconciliation |
| Money returned | Refund records in Logs, exportable to CSV | What comes back when an async task (images, music, video) fails or is settled at its actual usage; subtract it from usage |
| Totals by key, group and model | Keys and groups on the Dashboard | Seeing the structure and setting allocation ratios; counts usage without refunds, for reference only |
| Top-ups and credits | All records on the Top up page, split into online orders and credits | Checking credits, copying order numbers for invoices |
| Tokens of a single request | The usage field of each response | Finer allocation by end user or feature in your own system |
Exporting usage
- Open Logs in the console and set the time range to the whole month you are closing.
- Set the log type to Usage, so only the charges for calls are exported.
- To look at one project only, enter the key's name under API key name; you can also filter by model and group.
- Choose Export at the top right to download the CSV.
- Switch the log type to Refund, keep the other filters, and export again. Both exports get the same file name, so rename them after downloading, for example usage.csv and refunds.csv.
Each row of the CSV is one call, with columns for the time, type, model, group, API key, prompt tokens, completion tokens, cache read and write tokens, cost (¥), duration, request ID and more. Watch for three things:
- One export holds at most 20,000 records; with more, only the latest 20,000 are exported and the page tells you. For busy accounts, export by week, by day or by key.
- Dates and times follow the time zone of your browser: picking November 1 to November 30 means 00:00 on the 1st to 23:59:59 on the 30th, your local time. Teams in different time zones should agree on one before reconciling.
- The Group column of the CSV holds the group ID, while the page shows the group name. The mapping:
| Group | Group ID | Labels | Description | Models |
|---|---|---|---|---|
| Standard | default | Lowest priceMixed sources | Covers every model at the lowest price; some GPT and Claude routes are non-official | 618 |
| Azure | azure | Cloud | Microsoft Azure OpenAI — official, well priced, enterprise-grade | 116 |
| Azure Plus | azure-plus | Cloud | Premium Azure OpenAI line with o-series reasoning models | 135 |
| OpenAI Direct | openai | Official | OpenAI's own API | 169 |
| OpenAI Direct Plus | openai-plus | Official | The fastest, steadiest OpenAI line, incl. o-series and realtime | 174 |
| Official · Enterprise | official | Official | Enterprise line at official list prices, sourced from OpenAI and Anthropic, stability first | 309 |
| Claude Direct | claude-official | Official | Anthropic's own API; new models may have limited concurrency at launch | 47 |
| Claude List Price | claude-list | Official | Anthropic official line billed at list price | 47 |
| Claude Plus | claude | Mixed sources | Cost-effective Claude line; includes non-official sources, prices may change | 40 |
| Claude Lite | claude-lite | Mixed sources | The cheapest Claude line, non-official sources | 27 |
| Gemini Plus | gemini | Official | Google Gemini official line with video understanding | 70 |
| Gemini High Tier | gemini-pro | Official | Higher-quota Google Gemini official line | 70 |
| China Models | cn | Lowest price | DeepSeek, Qwen, Kimi, GLM, MiniMax and more at special prices | 195 |
| China Models 2 | cn-2 | — | Backup line for Chinese models | 18 |
| Economy (per token) | economy | Mixed sources | Non-official sources, billed per token at a discount | 42 |
| Economy (per call) | economy-call | Mixed sources | Non-official sources, billed per call — good for long prompts | 54 |
| Stable Diffusion | sd | — | Stable Diffusion image models | 5 |
| Video Line 1 | video-1 | Mixed sources | Veo and Grok video generation; non-official sources | 6 |
18 groups, from the live price list.
How to split the bill
| Basis | How | Notes |
|---|---|---|
| By project (key) | Sum Cost (¥) of usage by the API key column, minus refunds | The most common; the key name is the project |
| By group | Sum by the Group column | When a key has several groups, each request is recorded under the group that served it |
| By model | Sum by the Model column | Shows which models cost the most |
| By end user or feature | Record usage in your own system | The platform only records usage per key |
A pivot table in Excel does the job; for large files, a few lines of script are faster:
import csv
from collections import defaultdict
# Column names must match the export's header; use "Group" or "Model" to sum by group or model
GROUP_BY, COST = "API key", "Cost (¥)"
totals = defaultdict(float)
def add(path, sign):
# Exported files start with a BOM, so read them as utf-8-sig
with open(path, encoding="utf-8-sig", newline="") as f:
for row in csv.DictReader(f):
totals[row[GROUP_BY]] += sign * float(row[COST])
add("usage.csv", 1) # exported with the log type set to Usage
add("refunds.csv", -1) # exported with the log type set to Refund
for name, cost in sorted(totals.items(), key=lambda kv: -kv[1]):
print(f"{name}\t{cost:.2f}")The column names in the script must match the header of your export: replace API key with Group or Model to sum by group or by model. Some refund records carry no group and show up as a separate line when you sum by group.
Monthly reconciliation
- Early in the new month, export the previous month's usage records and refund records in full, in several parts if there are many.
- Sum usage by the API key column and subtract refunds to get each project's cost, then look at the Group and Model columns and flag projects that changed a lot.
- Check the total: in Logs, select the same time range and choose Show stats. Spend in period is the total cost of usage records in that range, before refunds, and should match the total of the usage CSV.
- Check credits: on the Top up page, open All records. The credits list online payments, redemption codes and balance adjustments by an administrator; match them against finance's payment records.
- Archive: keep the CSV and your summary in your own finance system or file storage rather than relying on the platform's records alone.
- For invoices, copy the order numbers from All records and request them as described below.
If your own system also records usage, spot-check a few requests by request ID to confirm that the tokens and costs agree.
Making next month easier
- Create a key before a new project goes live, rather than sharing one with another project.
- Disable keys you no longer use instead of deleting them. A disabled key still shows by name on the Dashboard; a deleted one shows only as a deleted key with its id, and refund records created after the deletion carry no key name.
- Give every key a spending cap, so one project's overrun cannot drain the whole account balance.
- If a key has several groups, requests that moved to a backup group are billed at the backup's price; look at the Group column separately when reconciling. See LLM API high availability.
Invoices
We issue both China domestic invoices (fapiao) and overseas invoices: add our WeChat support JsnonoChat and send your order number. Copy the order numbers from All records on the Top up page of the console. Billing, top-ups and invoices are summarized on the Billing page, bulk purchasing and offline payment on Enterprise, and the billing rules in detail in Billing and usage.
FAQ
Can usage be split by project?
Yes, as long as each project has its own key. Every call's cost is recorded under the key that made it, so summing the exported usage records by the API key column and subtracting that key's refund records gives each project's cost.
Is there a limit on exports?
One export holds at most 20,000 records. With more, only the latest 20,000 are exported and the page says so. Export by week, by day or by key to get everything.
What if the Dashboard and Logs disagree?
Go by Logs. The Dashboard sums whole hours and is written every few minutes, so the newest calls show up a little later; it is for reference only.
Can we split costs by our own customers or end users?
The platform records usage per key and does not know your end users. Record usage per end user in your own system from the usage field of each response, or give customers who are billed separately their own keys.
Can I get an invoice?
Yes. We issue both China domestic invoices (fapiao) and overseas invoices; add our WeChat support JsnonoChat and send your order number.