Skip to content

Track Sandbox costs

Check credit and wallet history, then attribute compute cost to API keys, Sandboxes, and charged runs.

Updated View as Markdown

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.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close