Use the public cost routes to attribute Sandbox compute to the API key that created each Sandbox.
These routes require usage:read and are available through direct HTTP, SDK 0.4.0, and the CLI.
The Sandboxes page in the BoxCompute dashboard provides the same account-owned breakdown.
Check credit and wallet history
GET /api/v2/billing and GET /api/v2/billing/transactions require usage:read, remain readable
at zero credit, and never start or resume compute. They return only the authenticated account’s data.
All monetary amounts are integer micro-USD: 1,000,000 micros is USD 1.
curl --fail-with-body -sS 'https://api.boxcompute.ai/api/v2/billing' \
-H "Authorization: Bearer $BOXCOMPUTE_API_KEY"An illustrative response with no running compute:
{
"billing": {
"currency": "usd",
"accountStatus": "active",
"balance": {
"cashMicros": 5000000,
"promoMicros": 2000000,
"planMicros": 0,
"totalMicros": 7000000,
"availableMicros": 7000000,
"reservedMicros": 0,
"expiringPromo": { "micros": 2000000, "expiresAt": 1791676800000 }
},
"settledUsage": { "aiMicros": 0, "sandboxMicros": 3000000, "totalMicros": 3000000 },
"activeEstimate": {
"status": "not_applicable",
"asOf": null,
"runtimeSeconds": 0,
"billableSeconds": 0,
"amountMicros": 0
},
"modelBillingMode": "observe"
}
}totalMicros is the wallet balance; availableMicros is spendable credit after reservations and
running compute. If live estimates fail, activeEstimate.status is unavailable and
availableMicros is null—unknown, not zero. settledUsage is all-time verified AI and compute
wallet deductions, not a date-window report, reservations, or running estimates. In observe
model billing mode, recorded AI costs do not debit the wallet. expiringPromo is nullable;
its expiresAt, like transaction timestamps, is Unix milliseconds.
Read one newest-first wallet page:
curl --fail-with-body -sS --get 'https://api.boxcompute.ai/api/v2/billing/transactions' \
-H "Authorization: Bearer $BOXCOMPUTE_API_KEY" \
--data-urlencode 'bucket=promo' \
--data-urlencode 'limit=20'The response is { "currency": "usd", "transactions": [...], "nextCursor": string | null }.
Each entry contains id, kind, bucket, signed amountMicros, description, createdAt,
and nullable expiresAt. Positive amounts add credit; negative amounts subtract it. Entries are
bucket-level, so one charge can have multiple entries. Pass nextCursor as before with the same
filters until it is null. limit is 1–200 (default 50). Optional filters are inclusive from
and exclusive to RFC 3339 timestamps, kind, and bucket (cash, promo, or plan).
SDK 0.4.0 unwraps the summary, but returns the transaction page directly:
const billing = await boxcompute.billing.get();
const page = await boxcompute.billing.transactions({
bucket: "promo",
limit: 20,
});
console.log(billing.balance.availableMicros);
console.log(page.nextCursor);billing = boxcompute.billing.get()
page = boxcompute.billing.transactions(
bucket="promo", limit=20,
)
print(billing.balance.available_micros)
print(page.next_cursor)These snippets use the authenticated client from the SDK quickstart; Python’s
date-start filter is from_. CLI 0.10.0 provides bxc credits, bxc billing transactions, and
bxc usage; see CLI commands.
Get an account report
Request the default 30-day window:
curl 'https://api.boxcompute.ai/api/v2/costs/sandboxes' \
-H 'Authorization: Bearer bc_live_REDACTED'Set an inclusive from and exclusive to with RFC 3339 timestamps when you need another period.
A window can span at most 400 days:
curl --get 'https://api.boxcompute.ai/api/v2/costs/sandboxes' \
-H 'Authorization: Bearer bc_live_REDACTED' \
--data-urlencode 'from=2026-09-01T00:00:00Z' \
--data-urlencode 'to=2026-10-01T00:00:00Z'The response groups the same costs by creating API key and by Sandbox:
{
"costs": {
"from": 1788220800000,
"to": 1790812800000,
"currency": "usd",
"estimates": "available",
"totals": {
"runs": 3,
"billableSeconds": 420,
"settledMicros": 7000,
"estimatedMicros": 500
},
"apiKeys": [
{
"apiKey": {
"id": "key_REDACTED",
"name": "Batch jobs",
"hint": "ab12",
"revoked": false
},
"sandboxes": 1,
"runs": 3,
"billableSeconds": 420,
"settledMicros": 7000,
"estimatedMicros": 500
}
],
"sandboxes": [
{
"id": "sbx_REDACTED",
"sandboxId": "sbx_REDACTED",
"name": "Data import",
"deleted": false,
"vmSandbox": true,
"size": "small",
"createdByApiKeyId": "key_REDACTED",
"createdAt": 1788220800000,
"deletedAt": null,
"firstStartedAt": 1788307200000,
"lastEndedAt": 1788912000000,
"runs": 3,
"billableSeconds": 420,
"settledMicros": 7000,
"estimatedMicros": 500
}
],
"unattributed": {
"runs": 0,
"billableSeconds": 0,
"settledMicros": 0,
"estimatedMicros": 0
}
}
}Amounts are integer millionths of the stated currency: 1,000,000 micros is USD 1. Settled
amounts are exact ledger charges for runs that ended in the window. estimatedMicros covers work
still running and is replaced by its settled charge after that run ends. estimates is
available, not_applicable, or unavailable; an unavailable estimate does not make settled
amounts approximate.
Billing is per second with a 60-second minimum for each run. A report includes active and deleted
Sandboxes. Its sandboxes rows identify the original customer-facing sandboxId, creation key,
runtime type and size, timestamps, run count, billable seconds, and settled and estimated amounts.
unattributed contains charges whose surviving records cannot identify a Sandbox.
Filter by one creating key with apiKeyId=key_REDACTED. Use apiKeyId=none for Sandboxes created
without an API key, such as from the dashboard or another account-owned product surface. Revoked
keys remain identifiable in historical results.
Inspect charged runs
Get every retained charged run plus any running estimate for an active Sandbox:
curl 'https://api.boxcompute.ai/api/v2/sandboxes/sbx_REDACTED/costs' \
-H 'Authorization: Bearer bc_live_REDACTED'For a deleted Sandbox, use the dsb_… deletion-record ID returned by
GET /api/v2/deleted-sandboxes:
API_BASE='https://api.boxcompute.ai/api/v2'
curl "$API_BASE/deleted-sandboxes/dsb_REDACTED/costs" \
-H 'Authorization: Bearer bc_live_REDACTED'The { "costs": ... } detail includes Sandbox and creating-key metadata, currency, estimate
status, settled runs, current running estimates, and truncated. Each settled run reports
startedAt, endedAt, runtimeSeconds, billableSeconds, rateMicrosPerMinute, and
amountMicros. At most 1,000 settled runs are returned; truncated: true means additional runs
were omitted. Deleted-Sandbox detail has no running estimate.
Cost lookups are limited to the authenticated account. An unknown or cross-account active or
deleted Sandbox returns 404.