Read the credit headers: audit every charge from the response
What you'll build: a thin client wrapper that logs what each call cost and what you have left, so your own logs become the billing audit trail.
| Section | API fundamentals |
|---|---|
| Actions used | POST /v1/data/contacts/verify-email |
| Credits | 1 (worst case) |
| Test-key safe | Yes — runs on qk_test_ for zero credits |
| Time to complete | ~5 min |
| Prerequisites | A key and any HTTP client that lets you read response headers. |
Three headers on every data call
X-Credits-Charged is what this call cost. X-Credits-Balance is what remains afterwards. X-Price-Book identifies the price book the charge was computed against, so a quote and a charge can always be traced to the same rules.
curl -i -X POST https://api.qannasapi.com/v1/data/contacts/verify-email \
-H "Authorization: Bearer $QANNAS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "jane@acme.example"}'
# < HTTP/1.1 200 OK
# < X-Credits-Charged: 1 # what this call cost
# < X-Credits-Balance: 94 # what is left afterwards
# < X-Price-Book: public # which rules were appliedLog the charge, not the estimate
Wrap your HTTP client once and record the three headers alongside request_id. That gives you per-call cost attribution without polling a usage endpoint, and request_id is what support will ask for if a charge ever looks wrong.
export async function call(action: string, body: unknown) {
const res = await fetch(`${API}/v1/data/${action}`, {
method: "POST",
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const json = await res.json();
// Your logs become the billing audit trail.
logger.info("qannas.call", {
action,
request_id: json.request_id,
charged: Number(res.headers.get("X-Credits-Charged")),
balance: Number(res.headers.get("X-Credits-Balance")),
});
return json;
}Watch the balance, not the clock
Because the balance comes back on every call, you can throttle or alert on the response you already have. There is no separate quota endpoint to poll and no lag between spending and knowing.
// The balance arrives on the call you already made —
// there is no quota endpoint to poll and no lag.
const balance = Number(res.headers.get("X-Credits-Balance"));
if (balance < LOW_WATER_MARK) {
pauseNonUrgentJobs();
alertOps(`credits low: ${balance}`);
}Summary
| Pattern | How |
|---|---|
| What this call cost | X-Credits-Charged |
| What is left | X-Credits-Balance |
| Which rules applied | X-Price-Book |
| Trace a charge | request_id in the response body |
| Throttle | Alert on X-Credits-Balance from the call you just made |
Production checklist
- Log X-Credits-Charged, X-Credits-Balance and request_id on every call.
- Alert on the balance header rather than polling a usage endpoint.
- Keep request_id — it is how a specific charge gets traced.
- Expect X-Credits-Charged: 0 on a miss and do not treat it as a failure.
Next steps
Run the estimate first. It costs nothing and it is the same arithmetic the meter will apply.