curl --request GET \
--url https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage \
--header 'Authorization: Bearer <token>'import requests
url = "https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"tier": "startup",
"balance_credits": 4820,
"reserved_credits": 335,
"included_credits": 3000,
"additional_credits": 2000,
"period_start": "2026-08-14T09:00:00Z",
"period_end": "2026-09-14T09:00:00Z",
"period_used_credits": 1180,
"allowance_resets_at": "2026-09-14T09:00:00Z",
"daily": [
{
"date": "2026-08-14",
"used_credits": 0
},
{
"date": "2026-08-15",
"used_credits": 940
},
{
"date": "2026-08-16",
"used_credits": 240
}
]
}{
"error": {
"code": "invalid_request",
"type": "invalid_request",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"retryable": true
}
}{
"error": {
"code": "invalid_request",
"type": "invalid_request",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"retryable": true
}
}{
"error": {
"code": "invalid_request",
"type": "invalid_request",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"retryable": true
}
}Account credit balance and period usage
The account’s balance, what it has spent in the current reporting period, and that spend day by day.
The period is not a Stripe subscription cycle yet, because no subscription exists. It is the whole month that began on the account’s own creation anniversary — the same shape a subscription cycle has, so the figures do not change shape when billing lands, and per-account rather than a calendar month, so an account created on the 28th is not shown three days of history and told it is a month.
allowance_resets_at is the date the plan’s included credits refill, and it is null on the free tier: that grant is issued once at signup and nothing refills it, so a date there would be a promise nothing keeps. additional_credits is what the account holds beyond what the plan included — a promotional grant, or a purchase — read from the credit lots, which are the only record of where a credit came from.
daily runs from the period’s first day through today (or through the period’s last day, once it is over), zero-filled, and always sums to period_used_credits. A day counts a credit when it was settled: a reservation is not spend, and credits released by a cancelled job were never used.
Refused with account_closed on an account that is being deleted or is deleted. That is the one account state this read refuses: deletion retains the credit records so a refund or a dispute can still be answered, and this is the operation that reads them. A suspended account is answered normally — a hold is a reason not to spend, not a reason to stop showing a customer what they have spent.
curl --request GET \
--url https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage \
--header 'Authorization: Bearer <token>'import requests
url = "https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://k8mfogcvz4.execute-api.us-east-1.amazonaws.com/prod/v1/usage")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"tier": "startup",
"balance_credits": 4820,
"reserved_credits": 335,
"included_credits": 3000,
"additional_credits": 2000,
"period_start": "2026-08-14T09:00:00Z",
"period_end": "2026-09-14T09:00:00Z",
"period_used_credits": 1180,
"allowance_resets_at": "2026-09-14T09:00:00Z",
"daily": [
{
"date": "2026-08-14",
"used_credits": 0
},
{
"date": "2026-08-15",
"used_credits": 940
},
{
"date": "2026-08-16",
"used_credits": 240
}
]
}{
"error": {
"code": "invalid_request",
"type": "invalid_request",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"retryable": true
}
}{
"error": {
"code": "invalid_request",
"type": "invalid_request",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"retryable": true
}
}{
"error": {
"code": "invalid_request",
"type": "invalid_request",
"message": "<string>",
"doc_url": "<string>",
"request_id": "<string>",
"retryable": true
}
}Authorizations
A Cognito access token, issued through the dashboard's own sign-up and sign-in pages (a backend-for-frontend; there is no Cognito Hosted UI) and sent as Authorization: Bearer <jwt>. Dashboard operations require this scheme and cannot be called with an API key, with no exception. GET /v1/usage and GET /v1/limits offered both schemes from 0.8.0; 0.8.1 withdrew that, because the control-plane API serves them alone and its authorizer has no API-key branch. An account_id supplied by the client is ignored; all reads/writes are scoped server-side to the authenticated account.
Response
Balance snapshot plus period usage and reservations.
What the account holds and what it has spent this period. See GET /v1/usage for what the period is while no subscription exists, and why allowance_resets_at is null on the free tier.
free, hobby, startup, growth, scale A non-negative JavaScript-safe integer credit amount. The upper bound matches Number.MAX_SAFE_INTEGER, which is enforced by the domain ledger so arithmetic and JSON round-trips cannot silently lose cents worth of credit precision.
0 <= x <= 9007199254740991A non-negative JavaScript-safe integer credit amount. The upper bound matches Number.MAX_SAFE_INTEGER, which is enforced by the domain ledger so arithmetic and JSON round-trips cannot silently lose cents worth of credit precision.
0 <= x <= 9007199254740991A non-negative JavaScript-safe integer credit amount. The upper bound matches Number.MAX_SAFE_INTEGER, which is enforced by the domain ledger so arithmetic and JSON round-trips cannot silently lose cents worth of credit precision.
0 <= x <= 9007199254740991A non-negative JavaScript-safe integer credit amount. The upper bound matches Number.MAX_SAFE_INTEGER, which is enforced by the domain ledger so arithmetic and JSON round-trips cannot silently lose cents worth of credit precision.
0 <= x <= 9007199254740991A non-negative JavaScript-safe integer credit amount. The upper bound matches Number.MAX_SAFE_INTEGER, which is enforced by the domain ledger so arithmetic and JSON round-trips cannot silently lose cents worth of credit precision.
0 <= x <= 9007199254740991When the plan's included credits next refill. null when nothing refills them — the free tier's grant is issued once at signup, and there is no sweep that renews it.
The period's spend by day, from its first day through today, zero-filled and always summing to period_used_credits. It stops at today rather than running to period_end: a zero for a day that has not happened is not a fact.
31Show child attributes
Show child attributes

