View script Copied!
Calculate On-Demand Sandbox (ODS) credits used from a Salesforce B2C Commerce ODS API response.
Salesforce B2C Commerce's On-Demand Sandbox feature bills by credit consumption - sandboxes accrue credits per minute based on whether they're running (1x/2x/4x multiplier depending on instance size) or stopped (0.3x). The ODS API returns raw minute counts; this script crunches them into human-readable breakdowns by sandbox count, uptime/downtime per profile, and total credits used.
Feed it a JSON response from the getRealmUsage endpoint (either as an argument or from your clipboard) and it calculates the credit math for you. Particularly useful for tracking burn rate across a billing period or explaining where credits went.
$ ods-usage '{"data":{"createdSandboxes":9,"activeSandboxes":8,"deletedSandboxes":0,"minutesDown":194006,"minutesUp":1389,"minutesUpByProfile":[{"profile":"medium","minutes":1050},{"profile":"large","minutes":289},{"profile":"xlarge","minutes":50}]}}'
Sandbox Counts
created: 9
active: 8
deleted: 0
Uptime & Downtime
min up: 1389
> medium: 1050
> large: 289
> xlarge: 50
min down: 194006
Credits Used
up: 1828
down: 58201
total: 60029
Feed JSON from a saved API response:
ods-usage "$(cat ods-report-2026-04.json)"
Pull JSON from clipboard (macOS via pbpaste):
ods-usage
Pipe directly from curl:
curl -s "https://admin.dx.commercecloud.salesforce.com/api/v1/realms/xxxx/usage?from=2026-04-01&to=2026-04-30&detailedReport=false" \
-H "Authorization: Bearer $TOKEN" | jq -c . | xargs -0 ods-usage
The script expects JSON matching the structure returned by the SFCC ODS API's getRealmUsage endpoint. Required fields under .data:
createdSandboxes - total sandboxes created during the periodactiveSandboxes - currently active sandboxesdeletedSandboxes - sandboxes deleted during the periodminutesDown - total minutes sandboxes were stoppedminutesUp - total minutes sandboxes were running (all profiles)minutesUpByProfile - array of objects with profile (string: "medium", "large", "xlarge") and minutes (number)Example minimal input:
{
"data": {
"createdSandboxes": 5,
"activeSandboxes": 4,
"deletedSandboxes": 0,
"minutesDown": 100000,
"minutesUp": 1200,
"minutesUpByProfile": [
{"profile": "medium", "minutes": 1200}
]
}
}
Three sections:
Credit multipliers per minute:
Headers are underlined when stdout is a terminal (via raw ANSI SGR codes).
The script does not accept flags. It takes a single optional argument:
pbpaste.| Code | Meaning |
|---|---|
| 0 | Success |
| 2 | Usage error (invalid JSON, missing required fields, no input) |
| 3 | Dependency error (jq missing; pbpaste missing in clipboard mode) |
jq - required for JSON parsingpbpaste (macOS) - required only if invoking without arguments (clipboard mode)pbpaste) is macOS-only. On other platforms, always pass JSON as an argument.