---
title: "How credits and success billing work"
url: "https://lookvalid.com/blog/product/how-credits-and-success-billing-work.md"
canonical_url: "https://lookvalid.com/blog/product/how-credits-and-success-billing-work"
last_updated: "2026-10-22"
type: "conceptual"
summary: "Exactly when a LookValid lookup reserves, charges or releases credits: found, not found, cache hits, errors and timeouts, with a table of outcomes."
related: ["https://lookvalid.com/docs/credits-and-billing.md", "https://lookvalid.com/docs/errors.md", "https://lookvalid.com/pricing.md", "https://lookvalid.com/docs/api/domain-age.md", "https://lookvalid.com/docs/quickstart.md"]
---

# How credits and success billing work

Exactly when a LookValid lookup reserves, charges or releases credits: found, not found, cache hits, errors and timeouts, with a table of outcomes.

Every LookValid lookup spends from one credit balance, and most of them charge only when they find something. This post follows a single request through the engine step by step: what is held, what is charged, what is released and what is stored. The table of outcomes at the center lists every case so you can predict a bill before you run a job.

## Prices and the two billing rules

Each product has a fixed price in credits per unit, read from the live catalog. For example, an IP lookup is 1 credit and a domain age lookup is 2. The [credits and billing](https://lookvalid.com/docs/credits-and-billing.md) page lists every product with its price and unit.

Most products use success billing: you are charged only when the lookup finds something. A few use per-call billing, where every completed lookup is charged whether it found something or not. Today the per-call product is Link Safety Check.

## What happens to one request

The engine handles a request in a fixed order, and the order explains most of the table below.

1. It checks the input against the product schema. A bad input is refused before anything else happens.
2. It checks your account cache. A fresh stored answer for the same product and the same normalized input is returned right away.
3. It checks that your account has fewer than 16 lookups running at once. Past that, the request is refused.
4. It reserves the product price from your available balance. This is a hold, not a charge. If the balance cannot cover it, the request stops here and the data source is never called.
5. It runs the lookup under the product time limit.
6. It settles. A found result turns the hold into a charge. A result that was not found releases the hold under success billing and charges it under per-call billing. Errors always release it.

The hold is set to outlast the time limit by a safety margin. If a hold ever expired before settlement, the answer would still be returned and would not be charged. Credits held by lookups still in progress show as reserved in your balance and come back if those lookups find nothing.

## The table of outcomes

Every row below follows from the engine order above. Charged means credits taken from your balance, and Stored means the answer is kept in your cache for the window in the next section.

What each outcome costs

| Outcome | HTTP status | Hold on balance | Charged | Stored |
| --- | --- | --- | --- | --- |
| Input fails the product schema | 400 | None | 0 | No |
| Same input answered earlier inside the cache window, found or not found | 200 | None | 0 | Already stored, cache_hit is true |
| Account already has 16 lookups running | 429 | None | 0 | No |
| Balance below the product price | 402 | Refused | 0 | No, the data source is not called |
| Found, any product | 200 | Held, then committed | Full product price | Yes |
| Not found, success billing | 200 | Held, then released | 0 | Yes, with the reason |
| Not found, per-call billing | 200 | Held, then committed | Full product price | Yes, with the reason |
| Data source unavailable or lookup timed out | 503 | Held, then released | 0 | No |
| Provider rejects the input after it ran | 400 | Held, then released | 0 | No |
| Unexpected internal error | 500 | Held, then released | 0 | No |

On the success-billing rows, `found: false` is a normal answer with HTTP 200, not an error. It carries `credits_charged: 0` and a `reason`. Branch on `found`, not on the status code.

## The cache window

Results are cached per account, and both found and not found answers are stored. A repeat of the same lookup inside the window returns the stored result with `cache_hit: true` and charges nothing. Another account that runs the same lookup pays for its own first one. Inputs are normalized before the cache key is built, so letter case or surrounding spaces do not make a new lookup. The longest window is 7 days.

Cache window by product

| Window | Products |
| --- | --- |
| 7 days | phone, country-code, email-domain-check, ip, phone-spam, carrier-lookup, vin-decoder, link-in-bio-lookup, domain-authority, domain-age, website-scraper, website-contacts-scraper |
| 6 hours | link-safety |
| 30 minutes | site-files |

Two identical requests that are in flight together are handled safely: the first to settle is charged and stored, and the second is returned from that stored entry without a second charge. The `cache` object in each response shows `cached_at` and `expires_at`, so you can see when a stored answer ages out.

## Reading the charge and checking your balance

Each lookup response carries `credits_charged` and `credits_remaining`, also sent as the `X-Credits-Charged` and `X-Credits-Remaining` headers. A call to `GET /v1/account` returns your granted, spent, reserved and available credits and never costs anything.

Here is a lookup whose cost depends on the result. A registered domain finds data and is charged. An unregistered domain returns `found: false` and is free, because domain age uses success billing.

Look up a domain, charged only when it is registered

```bash
curl -X POST https://YOUR_API_HOST/v1/domain-age \
  -H "Authorization: Bearer $LOOKVALID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"example.com"}'
```

- Do not retry a `found: false` result. It returns the same answer, free, until the window ends.
- Cache results on your side if you need them for longer than the window.
- Check the unit column on the credits and billing page: it says what one charge covers, such as one domain or one VIN.

To see these rules on your own data, run the example above with a key and then read the response headers. The [quickstart](https://lookvalid.com/docs/quickstart.md) covers creating the key, and the [domain age product page](https://lookvalid.com/products/domain-age.md) lists the fields in the result.

By LookValid engineering. Published 2026-10-19, updated 2026-10-19.

## Related

- [Credits and billing](https://lookvalid.com/docs/credits-and-billing.md)
- [Errors](https://lookvalid.com/docs/errors.md)
- [Plans, trial and credit pricing](https://lookvalid.com/pricing.md)
- [Domain Age reference](https://lookvalid.com/docs/api/domain-age.md)
- [Quickstart](https://lookvalid.com/docs/quickstart.md)
