# Cluster Usage & Costs API
AI agents and LLMs: before exploring further, fetch the full index of Typesense documentation with descriptions at https://typesense.org/docs/llms.txt.
This API lists the node-hours and outbound bandwidth your account was invoiced for, and what each cluster cost per month. For what a new cluster would cost, see the Prices API.
All amounts are in US cents, and timestamps are Unix timestamps in seconds.
# List usage
This endpoint lists every node-hour and every amount of outbound bandwidth your account was billed for, one row per billed usage period.
Here's how to list one cluster's usage from a given time onward:
curl --get --location "https://cloud.typesense.org/api/v1/account/usage" \
-H "Accept: application/json" \
-H "X-TYPESENSE-CLOUD-MANAGEMENT-API-KEY: YOUR-API-KEY" \
--data-urlencode "start_time=1761004800" \
--data-urlencode "cluster_ids=0197kdlrfsubahw4p"
Query Parameters:
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
| start_time | Optional | integer | 7 days before end_time | Unix timestamp (seconds), inclusive. Only rows billed at or after this time. Not applied when invoice_id is set. |
| end_time | Optional | integer | 10 minutes ago | Unix timestamp (seconds), exclusive. Only rows billed before this time. A later value is capped at 10 minutes ago. The window can span at most 31 days. Not applied when invoice_id is set. |
| cluster_ids | Optional | string | Comma-separated cluster IDs, at most 100. Only rows for these clusters. Rows of a cluster you have since transferred to another account stay listed: read them without this filter, or by invoice_id. | |
| invoice_id | Optional | string | Only rows on this invoice, no matter when they were billed. Use the id returned by List all invoices or a row's invoice_id. | |
| page | Optional | integer | 1 | Page number for pagination |
| per_page | Optional | integer | 100 | Number of rows per page (maximum 500) |
Response:
{
"page": 1,
"per_page": 100,
"total": 2,
"start_time": 1761004800,
"end_time": 1761090600,
"usage": [
{
"id": "7187ecb97e84ae30b027429c",
"type": "node",
"billed_at": 1761011400,
"invoice_id": "inv_abc123def456",
"invoice_status": "draft",
"price_tier_id": "59e21f1e-ccf8-11f1-baf2-d6db8e0b3c14",
"cluster_id": "0197kdlrfsubahw4p",
"node_hostname": "0197kdlrfsubahw4p-1.a1.typesense.net",
"region": "oregon",
"period_starts_at": 1761001200,
"period_ends_at": 1761008400,
"node_hours": 2,
"price_per_node_hour_cents": 12,
"configuration": {
"memory": "4_gb",
"vcpu": "2_vcpus",
"gpu": "no",
"high_performance_disk": "no",
"high_availability": "no",
"search_delivery_network": "off",
"load_balancing": "no"
}
},
{
"id": "9812a81108d3e00209dd4f17",
"type": "bandwidth",
"billed_at": 1761012000,
"invoice_id": "inv_abc123def456",
"invoice_status": "draft",
"price_tier_id": "59e1cd5c-ccf8-11f1-baf2-d6db8e0b3c14",
"cluster_id": "0197kdlrfsubahw4p",
"region": "oregon",
"period_starts_at": 1761001200,
"period_ends_at": 1761008400,
"bandwidth_kb": 183402,
"price_per_gb_cents": 9
}
]
}
Rows are ordered by billed_at, oldest first.
start_time and end_time in the response are the window that was actually applied, after the 10-minute cap.
Both are null when you pass invoice_id.
# Usage Row Fields
Every row has these fields:
| Field | Type | Description |
|---|---|---|
| id | string | Stable row ID. Use it to de-duplicate rows you have already read. |
| type | string | node or bandwidth (see below). |
| billed_at | integer | When the row was billed, as a Unix timestamp. start_time and end_time filter on this field. |
| invoice_id | string | The invoice this row is on, as returned by the Invoices API. |
| invoice_status | string | The invoice's status now: draft, due, paid, uncollectible or voided. Rows are listed in every status, since a status can change later, for example from uncollectible to paid. |
| price_tier_id | string | The price tier the invoice groups this row under. You want to treat it as an opaque ID. Invoice line items carry the same price_tier_id. |
| cluster_id | string | The cluster this usage belongs to. |
| region | string | The region this usage was in, for example oregon. |
| period_starts_at | integer | Start of the period this row covers, as a Unix timestamp. |
| period_ends_at | integer | End of the period this row covers, as a Unix timestamp. |
# Row Types
| Type | Fields |
|---|---|
node | node_hostname: the node's hostname, or null when it is not known.node_hours: whole node-hours. Each period is rounded up from the node's own start time, instead of from the clock hour.price_per_node_hour_cents: the price charged per node-hour for this row, in cents, after any free allowance.configuration: the node's configuration as it was priced, using the same names and values as the cluster resource. |
bandwidth | bandwidth_kb: outbound bandwidth from the cluster's nodes in this region during the period, in KB, including replication traffic between the cluster's nodes.price_per_gb_cents: the price per GB for this row's price tier, in cents. |
# How rows add up to invoice line items
Each node and bandwidth line item on an invoice covers the rows on that invoice with the same type, cluster_id and price_tier_id, and carries that price_tier_id itself:
- For node line items,
quantityis the sum ofnode_hoursover those rows, andprice_centsis that sum multiplied byprice_per_node_hour_cents. - For bandwidth line items, the invoice sums
bandwidth_kbover those rows, then rounds the total up to whole GB once:quantityisceil(sum_of_bandwidth_kb / 1000000), andprice_centsisquantity * price_per_gb_cents.
For example, three bandwidth rows of 183,402 KB, 2,450,100 KB and 96,000 KB with the same cluster_id and price_tier_id add up to 2,729,502 KB, which the invoice bills as 3 GB.
If you round each row up on its own, you'd get 5 GB instead.
Two price tiers can have the same price, and the invoice keeps them on separate lines.
So grouping by price would merge rows the invoice doesn't.
Node and bandwidth tiers are numbered separately, so the same price_tier_id can show up on both a node row and a bandwidth row.
A usage period that crosses a price tier boundary, such as the end of a free allowance, shows up as one row per tier.
Both rows carry the same period, and their node_hours or bandwidth_kb add up to the usage for that period.
Bandwidth uses decimal units: 1 KB is 1,000 bytes and 1 GB is 1,000,000 KB.
# Reading new usage as it is billed
A row shows up once its usage is billed, 1 to 3 hours after the usage happens.
Here's how to read every row exactly once:
- Call the endpoint with a
start_time. The response'send_timeis the end of the window that was applied. - Fetch the remaining pages with the same
start_timeand thatend_time, so every page reads the same window. - On your next poll, pass that
end_timeas the newstart_time.
If start_time is less than 10 minutes in the past, the response is empty and its end_time equals start_time, so you can keep polling with the same value.
# Reconciling an invoice
Summing the rows of one invoice_id as described above reproduces the invoice's node and bandwidth line items.
A draft invoice keeps gaining rows while it's still a draft.
# What this endpoint does not include
Support plans, prepaid credit purchases, credits and refunds are on your invoices, so you want to use the Invoices API for those.
# List costs by cluster
This endpoint lists what each cluster cost you per calendar month, for the current month so far and the months before it.
Here's how to list the last 2 months:
curl --get --location "https://cloud.typesense.org/api/v1/account/cluster-costs" \
-H "Accept: application/json" \
-H "X-TYPESENSE-CLOUD-MANAGEMENT-API-KEY: YOUR-API-KEY" \
--data-urlencode "months=2"
Query Parameters:
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
| months | Optional | integer | 4 | How many months to list, ending with the current month. From 1 to 12. |
Response:
{
"currency": "usd",
"months": [
{
"month": "2026-09",
"starts_at": 1788220800,
"ends_at": 1790812800,
"complete": true,
"total_cents": 48210,
"other_charges_cents": 4900,
"clusters": [
{
"cluster_id": "0197kdlrfsubahw4p",
"name": "products-prod",
"compute_cents": 36000,
"bandwidth_cents": 1250,
"backup_storage_cents": 860,
"total_cents": 38110
},
{
"cluster_id": "x8n2kq0wd1mfz7b3c",
"name": null,
"compute_cents": 5200,
"bandwidth_cents": 0,
"backup_storage_cents": 0,
"total_cents": 5200
}
]
},
{
"month": "2026-10",
"starts_at": 1790812800,
"ends_at": 1793491200,
"complete": false,
"total_cents": 21400,
"other_charges_cents": 0,
"clusters": [
{
"cluster_id": "0197kdlrfsubahw4p",
"name": "products-prod",
"compute_cents": 20500,
"bandwidth_cents": 900,
"backup_storage_cents": 0,
"total_cents": 21400
}
]
}
]
}
Months are listed oldest first, and the clusters in each month are listed highest total_cents first.
# How charges are split across clusters
A month holds what was actually charged in it: card payments and prepaid credit spent, by charge date in UTC.
Each charge is split across the clusters on the invoice it paid, in proportion to that invoice's line items.
So the clusters' total_cents plus other_charges_cents add up to the month's total_cents, to the cent.
# Month Fields
| Field | Description |
|---|---|
month | The calendar month, as YYYY-MM in UTC. |
starts_at | Unix timestamp in seconds when the month starts. |
ends_at | Unix timestamp in seconds when the next month starts. |
complete | false for the current month, which can still take charges. |
total_cents | Everything charged in the month. |
other_charges_cents | Charges that aren't for a cluster, like support plans. |
clusters | One entry per cluster that was charged in the month. |
# Cluster Fields
| Field | Description |
|---|---|
cluster_id | The cluster ID. |
name | The cluster's current name. null when it has no name, or has since been transferred to another account. |
compute_cents | The cluster's share of the month's charges for node-hours. |
bandwidth_cents | The cluster's share for outbound bandwidth. |
backup_storage_cents | The cluster's share for backup storage. |
total_cents | compute_cents + bandwidth_cents + backup_storage_cents. |
# When costs are being prepared
For an account with a long billing history, the first read can take a minute or two to prepare.
While that runs, this endpoint returns HTTP 503 with a Retry-After header in seconds:
{
"success": false,
"message": "Cluster costs for this account are being prepared. Retry in a minute."
}
# Permissions
To list usage or list costs by cluster, you need a key with the billing:read capability.
See capabilities.
This documentation site is open source. Found an issue? Edit this page (opens new window) and send us a Pull Request.
For AI Agents: View an easy-to-parse, token-efficient
Markdown version of this page. You can also replace
.html with .md in any docs URL. For paths ending in /, append
README.md to the path.