Skip to content
TutujinAPI

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

DataWhereUse it for
The cost of every callUsage records in Logs, exportable to CSVThe basis for reconciliation
Money returnedRefund records in Logs, exportable to CSVWhat 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 modelKeys and groups on the DashboardSeeing the structure and setting allocation ratios; counts usage without refunds, for reference only
Top-ups and creditsAll records on the Top up page, split into online orders and creditsChecking credits, copying order numbers for invoices
Tokens of a single requestThe usage field of each responseFiner allocation by end user or feature in your own system

Exporting usage

  1. Open Logs in the console and set the time range to the whole month you are closing.
  2. Set the log type to Usage, so only the charges for calls are exported.
  3. To look at one project only, enter the key's name under API key name; you can also filter by model and group.
  4. Choose Export at the top right to download the CSV.
  5. 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:
GroupGroup IDLabelsDescriptionModels
StandarddefaultLowest priceMixed sourcesCovers every model at the lowest price; some GPT and Claude routes are non-official618
AzureazureCloudMicrosoft Azure OpenAI — official, well priced, enterprise-grade116
Azure Plusazure-plusCloudPremium Azure OpenAI line with o-series reasoning models135
OpenAI DirectopenaiOfficialOpenAI's own API169
OpenAI Direct Plusopenai-plusOfficialThe fastest, steadiest OpenAI line, incl. o-series and realtime174
Official · EnterpriseofficialOfficialEnterprise line at official list prices, sourced from OpenAI and Anthropic, stability first309
Claude Directclaude-officialOfficialAnthropic's own API; new models may have limited concurrency at launch47
Claude List Priceclaude-listOfficialAnthropic official line billed at list price47
Claude PlusclaudeMixed sourcesCost-effective Claude line; includes non-official sources, prices may change40
Claude Liteclaude-liteMixed sourcesThe cheapest Claude line, non-official sources27
Gemini PlusgeminiOfficialGoogle Gemini official line with video understanding70
Gemini High Tiergemini-proOfficialHigher-quota Google Gemini official line70
China ModelscnLowest priceDeepSeek, Qwen, Kimi, GLM, MiniMax and more at special prices195
China Models 2cn-2—Backup line for Chinese models18
Economy (per token)economyMixed sourcesNon-official sources, billed per token at a discount42
Economy (per call)economy-callMixed sourcesNon-official sources, billed per call — good for long prompts54
Stable Diffusionsd—Stable Diffusion image models5
Video Line 1video-1Mixed sourcesVeo and Grok video generation; non-official sources6

18 groups, from the live price list.

How to split the bill

BasisHowNotes
By project (key)Sum Cost (¥) of usage by the API key column, minus refundsThe most common; the key name is the project
By groupSum by the Group columnWhen a key has several groups, each request is recorded under the group that served it
By modelSum by the Model columnShows which models cost the most
By end user or featureRecord usage in your own systemThe platform only records usage per key

A pivot table in Excel does the job; for large files, a few lines of script are faster:

Python
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

  1. Early in the new month, export the previous month's usage records and refund records in full, in several parts if there are many.
  2. 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.
  3. 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.
  4. 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.
  5. Archive: keep the CSV and your summary in your own finance system or file storage rather than relying on the platform's records alone.
  6. 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.