Track usage and spend¶
GET /v1/usage answers with the balance and the counters for the current
period. This guide covers reading it, what each figure counts, and reconciling
it against your own records.
One credit is one US cent and buys the recognition of one document. Every figure below is in those units.
Read the counters¶
The call takes the same Authorization header a scan does and returns 200.
curl
curl https://api.doc.cheap/v1/usage \
-H "Authorization: Bearer sk_sandbox_public"JavaScript
const response = await fetch("https://api.doc.cheap/v1/usage", {
headers: { Authorization: "Bearer sk_sandbox_public" },
});
const usage = await response.json();
console.log(usage.balance_credits, usage.credits_spent, usage.scans.total);Python
import json
import urllib.request
request = urllib.request.Request(
"https://api.doc.cheap/v1/usage",
headers={"Authorization": "Bearer sk_sandbox_public"},
)
with urllib.request.urlopen(request) as response:
status = response.status
usage = json.load(response)
print(usage["balance_credits"], usage["credits_spent"], usage["scans"]["total"])The body has four parts.
| Key | Carries |
|---|---|
balance_credits |
Credits available to the account right now, or null for a key with no account |
period |
The bounds of the current period, as a UTC calendar month |
scans |
total, billed, and by_status with one count per recognition status |
credits_spent |
Credits charged within the period |
balance_credits is a current figure and does not belong to the period.
Everything else in the body does.
Read the status breakdown¶
scans.by_status carries one count for each of the five recognition
statuses.
| Status | Means |
|---|---|
recognized |
The document type was determined and a zone or the printed page was read |
no_document_found |
Nothing in the frame was located as a document |
unsupported_document |
A document was located, and its type is not one the engine reads |
unreadable |
The type was determined and no source could be read |
rejected |
Recognition ran and the result was not usable |
scans.total is every scan the period saw. scans.billed is the subset that
drew a credit, and it is the figure to compare against credits_spent.
The two are not the same question. A scan can be billed without being recognized, which is why both counts are published: see what a billed scan is.
Reconcile against your own records¶
Keep meta.billed from every scan response and sum it over the same period.
Your sum and scans.billed are the two sides to compare.
Three properties make the comparison work.
- Every settled scan is counted, whether or not its result was stored. The figures do not decay as retention windows pass, so a month-old total does not shrink.
- A zero-retention scan still counts.
retain_hours: 0leaves no row to read back, and the counter was incremented at settlement. - A replayed request is counted once. An
Idempotency-Keythat returns the first result charges nothing the second time and adds nothing here.
If your sum is higher than ours, look for a retry without an idempotency key that you counted twice. If ours is higher, look for a response your own code dropped before recording it.
Know which key reads what¶
A sandbox key of your own account reads that account's real balance and counters. Usage is an account-level question, and the answer does not change with the key that asked it.
The public sandbox key belongs to no account. It answers with a well-formed body carrying a null balance and zero counters, rather than an invented example.
Neither sandbox key ever adds to credits_spent. A registered sandbox key is
answered from a fixed synthetic specimen and is never charged.
Handle the period rollover¶
The period is a UTC calendar month, and period.start and period.end name
its bounds.
At the rollover the counters return to zero and balance_credits does not.
Credits carry over; the counters describe the month.
Read period.start before you store a reading. A job that runs near midnight
UTC can take two readings belonging to different months. The bounds in the body
are what tells them apart.
Nothing expires at the rollover. A balance is spent when it is spent, and no figure here is a monthly allowance.
Watch the balance from a deployment¶
Poll GET /v1/usage on a schedule and alert on balance_credits below a
threshold you choose. Size the threshold on your own daily volume.
A balance that reaches zero does not go negative. The next scan is refused with
402 insufficient_credits, before the engine
is called and before anything is charged.
The dashboard shows the same figures with the operations log beside them, at https://doc.cheap/app. The log lists the individual scans; this endpoint is the aggregate.
Next¶
- Top up with crypto — putting credits on the balance.
- What a billed scan is — the predicate
behind
billed. - Limits — the rate this endpoint shares with the rest.