POST https://api.zeroclick.io/v1/usage/check (API key scope usage:read). The body carries the request’s zcRequestId, the serviceSlug, and 1 to 20 usage items: one per meter, no duplicates. The response is a pure decision:
Request
Response
The three usage-item forms
Each usage item names a meter and sizes the usage one of three ways. An item may not declare both a quantity and a ceiling.quantity: the exact amount, known up front (“this call is 1 request”).maxQuantity: a ceiling for work you cannot size in advance (“at most 8,192 output tokens”). The check gates at the ceiling: could the largest allowed call go through?- Neither: the item falls back to the meter’s
defaultMaxQuantityfrom the plan meter price and gates at that ceiling. If the meter has no default, there is nothing to gate against, and the check deniesmeter_not_priced.
The seven denial reasons
allowed: false always comes with exactly one machine-readable reason:
Your API turns a denial into the
402 payment_required refusal body, and ZeroClick re-prices it into the buyer’s next challenge. A denial is a payment prompt, not a dead end. The errors reference lists the response shapes.
Free mode
Prices can carryincludedUnits: free units per period before the price applies. On pay-as-you-go, consuming them is an explicit opt-in: the agent sends the zc-mode: free request header on each call. A missing or unrecognized header means paid; ZeroClick never rejects a call over it. Anonymous free-mode calls are never served free, and neither are unclaimed agents: the allowance is reserved for agent identities claimed by a human with a verified email, and it is scoped to that buyer - consumption aggregates across every agent the same human owns, so claiming more agents never grants more free usage. ZeroClick answers anonymous calls with a $0 identity challenge first, and the identified retry gets the real coverage check, including the claimed-and-verified requirement. ZeroClick records the mode on the request, so your allowance check and the usage recorder honor the same decision ZeroClick made. See free and identity endpoints.
Settling usage: sync and async
A check gates; a settlement records. There are two ways to settle, and both write the same usage events:-
Sync (preferred): put a
zc-usageheader on your 2xx response. ZeroClick records it while returning the response and strips the header before the agent sees it. A request can never settle the same meter twice. -
Async: call
POST https://api.zeroclick.io/v1/usage(scopeusage:write) withzcAgentId,serviceSlug,meterSlug,quantity, an optionaloccurredAt, and anidempotencyKey. Async events are unique per(service, idempotencyKey). Keys are yours and must be derived, never random (zcreq_8h2m4x0q9k1f_output_tokens), so a retry reproduces the same key. A replay answers"recorded": true, "duplicate": truewith the originally stored event: a success, not an error.
source: "sync" or "async", along with the zcAgentId, zcRequestId, meterSlug, quantity, and the computed totalCostUsd. This is the same record you see in the dashboard and the REST API. ZeroClick can also refuse a report after the fact: 402 for access_inactive, plan_expired, or usage_exhausted, 409 for meter_not_priced, and 404 otherwise. That is one more reason to check before you serve. The settle usage guide covers both paths in code.