Billing and usage #
Wallet balance, spendable funds, in-flight holds, and the usage summary endpoint.
DataDistillers bills per-job by actual GPU compute time, not file size or page count. This guide covers how to read your wallet, distinguish spendable funds from in-flight holds, and pull a usage summary.
The billing model
A job's cost = (per-second compute rate) × (actual GPU seconds). No per-page charge, no per-file fee, no minimum.
When you submit a job:
- The platform places a hold on your wallet for an estimated cost.
- The job runs.
- On completion, the hold is settled to the actual cost, usually less than the hold.
- The difference is released back to spendable balance.
If a job fails or is cancelled, the entire hold is released. You only pay for compute that produced a result.
Reading the wallet
GET /wallet returns three numbers:
curl -u "$DD_KEY:$DD_SECRET" \ https://api.datadistillers.com/api/v1/wallet
{
"balance": 125.40,
"spendable": 119.85,
"is_frozen": false,
"frozen_reason": null
}
| Field | Meaning |
|---|---|
balance | Total credits deposited and not yet spent. |
spendable | balance minus funds held by in-flight jobs. The amount available to start new jobs. |
is_frozen | If true, no new jobs can be started. See frozen_reason. |
frozen_reason | Human-readable cause: payment_failed, manual_freeze, compliance_review, etc. |
The gap between balance and spendable reflects in-flight holds. After
all in-flight jobs complete, spendable rises back to balance (less the
actually-spent portion).
Handling a frozen wallet
A frozen wallet rejects new submissions with 402 Payment Required. The
freeze persists until cleared by the trigger:
frozen_reason | Cleared by |
|---|---|
payment_failed | Add funds via the dashboard. Auto-recharge cards retry on next deposit attempt. |
manual_freeze | Lift the freeze in the dashboard. |
compliance_review | Resolved by support. |
In-flight jobs already accepted before the freeze run to completion and charge normally. The freeze affects only new submissions.
Usage summary
GET /usage?period={7d|30d|90d} returns aggregated spend over a rolling
window:
curl -u "$DD_KEY:$DD_SECRET" \ 'https://api.datadistillers.com/api/v1/usage?period=30d'
{
"period": "30d",
"period_start": "2026-04-03T00:00:00Z",
"period_end": "2026-05-03T00:00:00Z",
"total_jobs": 2841,
"successful_jobs": 2779,
"failed_jobs": 62,
"total_spend": 87.42
}
total_spend is the sum of cost across all completed jobs in the window.
In-flight holds are excluded; only finalised charges count. So
total_spend for a window that ends "now" can be lower than what the
wallet shows as the recent spend, because the most recent jobs may still be
held.
Building a balance monitor
A simple alerting cron that pages on low balance:
import os, requests
THRESHOLD = 50.00 # warn when spendable drops below this
AUTH = (os.environ['DD_KEY'], os.environ['DD_SECRET'])
w = requests.get('https://api.datadistillers.com/api/v1/wallet', auth=AUTH).json()
if w['is_frozen']:
page(f"DD wallet frozen: {w['frozen_reason']}")
elif w['spendable'] < THRESHOLD:
warn(f"DD spendable below threshold: ${w['spendable']:.2f}")
Run it every 5–15 minutes from cron or your scheduler. Pair with the usage endpoint for a weekly spend digest if budgets matter to your org.
Per-job cost visibility
The cost of an individual job appears on the artifact response after
completion. Look at processing_duration_seconds and the per-second rate
on your account:
curl -u "$DD_KEY:$DD_SECRET" \
https://api.datadistillers.com/api/v1/artifacts/art_b4d8c0f1 | \
jq '{ duration: .processing_duration_seconds, status: .status }'
For finer granularity (e.g. tracking spend per template or per business
unit), correlate artifact_id against tags you set at submit and
aggregate in your data warehouse; there's no built-in segmentation in
the usage endpoint.