ALL POSTS
creditsapi pricingapi designmetering

What are API credits? How credit-based APIs meter usage

An API credit is a unit of consumption the provider defines, not a rebranded request. Here is what limit, remaining, refill and overage actually mean, why one endpoint costs 1 credit and another 250, and what a failed request does to your balance.

Sorower

Sorower

Co-founder

Aug 11, 202614 min read
In this article

A pricing page says 50,000 credits per month. Another says 2,000 API calls. A third says 1,000 credits, and mentions further down that one search costs two of them.

Only one of those numbers tells you what you can actually do, and it isn't the one you think.

API credits are a unit of consumption that the provider defines, deducted from a balance as you use the API. That definition sounds like bureaucracy until you notice what it buys: a credit is not a rebranded request. It exists so the thing being counted can stop being requests and start being work. This post covers what an API credit actually is, the four fields every credit balance is built from, why one endpoint costs 1 credit and another costs 250, and the question almost nobody answers on their pricing page: what happens to your balance when a request fails.

What are API credits, exactly?

An API credit is a unit of consumption defined by the provider and deducted from a prepaid or allocated balance when you call the API.

That is the dictionary version. The useful version is the property underneath it: credits decouple the unit you charge in from the unit the client happens to send.

A request is defined by HTTP. One connection, one method, one path, one response. You do not get to redefine it and neither does your customer. A credit is defined by you. If a search costs 2 and a bulk export costs 60, that is not an approximation of request counting, it is a different measurement entirely.

Which leads to the part pricing pages tend to skip. A credit number on its own is meaningless. "50,000 credits" tells a customer nothing until they can see the table that says what their operations cost. A provider who publishes the first number prominently and buries the second has made a choice, and it is not one made in your favour.

Credits vs raw request counts

Request counting works fine right up until it doesn't, and it always breaks in the same place: the day two calls that cost you wildly different amounts to serve both count as 1.

Picture a health check and a crawl of 250 pages. Same client, same API, same auth header. One answers in milliseconds out of memory. The other holds a worker for a minute and burns real egress. Under request counting they are identical. Under credit counting you get to say they are not.

Request count

Credit

Defined by

HTTP. One call is one call.

You. A credit is whatever you declare it to be.

Measures

Transport volume

Work performed or value delivered

Can express

How many times someone called you

Operation type, result volume, quality tier, success or failure

Breaks when

Two calls cost very different amounts to serve

Your table drifts from your real costs, or customers can no longer predict a bill

There are four things a credit can absorb that a request count cannot:

  • Operation type. A read and a re-index are not the same event.

  • Result volume. One request that returns 500 rows did 500 rows of work.

  • Quality tier. "Basic" and "advanced" modes of the same endpoint have different costs behind them.

  • Outcome. You can decline to charge for work that didn't succeed.

That last one is the one people forget at design time and remember in the support queue.

So is a credit just a request with a multiplier? Sometimes, yes, and when that is all it is you have added a unit of confusion for no gain. If every operation you sell costs one credit, you have invented a second name for "request" and now your customers have to do arithmetic to understand your pricing page. Credits earn their complexity only when the multiplier genuinely varies.

The four fields every credit balance is built from

Strip any credit system down and the same four fields are underneath: limit, remaining, refill, and overage. Every one of them is a policy decision, and if you don't make it deliberately you will make it by accident, in a support thread, on the last day of a month.

limit: the ceiling

How much the customer may consume in a period. The interesting question is not the number, it is whose ceiling it is. Attach the pool to each API key and a customer with five keys for five environments quietly has five times the quota you sold them. Attach it to the customer and all their keys draw from one balance.

ReqKey puts the pool on the consumer, the entity that represents one of your customers, so every key that customer holds shares it. That is a deliberate correction: per-key pools multiply an entitlement by a number that has nothing to do with what was sold.

remaining: the only number your customer looks at

remaining is limit minus what has been used. It sounds too obvious to discuss, right up until you notice how many APIs make you call a separate billing endpoint to find it. Put it in the response of the call that spends it. A client that learns its balance on every request can degrade gracefully. A client that has to go ask will find out when it gets rejected.

refill: how it comes back

Two independent axes hide in this one word, and conflating them is where most credit systems get confusing.

The first is the schedule: duration-based (every 30 days from whenever they signed up) or calendar-based (the 1st of each month, same for everyone). Duration-based is fairer to the customer and harder to reconcile against a monthly invoice. Calendar-based is the reverse.

The second is the policy, and it decides the answer to the question every customer eventually asks: what happens to the credits I didn't use?

  • reset replaces whatever is left with the fresh allowance. Unused credits are gone.

  • add accumulates the new allowance on top of the remaining balance.

  • carryover is the middle path: leftovers roll forward, but only up to a cap.

That cap exists for a reason. Pure accumulation means a customer who under-uses for eight months arrives in month nine with an enormous balance and a workload you never provisioned for. Pure reset means a customer who paid for capacity watches it evaporate at midnight. The cap is where most providers land, and it should be stated on the pricing page rather than discovered.

overage: what happens at zero

Overage decides whether remaining may go below zero, and how far. It is the difference between a hard wall and a soft one. Without it, hitting zero mid-batch stops a customer dead. With it, they get a defined amount of rope.

Here is a plan configured with all of it, in ReqKey's documented shape:

{
  "planName": "Pro Plan",
  "credits": {
    "limit": 5000,
    "overage": { "enabled": true, "limit": 500 },
    "refill": {
      "every": "30d",
      "refillCredit": 5000,
      "refillPolicy": "add",
      "carryover": { "enabled": true, "max": 2000 }
    }
  }
}

Read it back in English: 5,000 credits, topped up by another 5,000 every 30 days, leftovers roll forward but never more than 2,000 of them, and a customer may run 500 credits into the red before anything is refused. Four fields, one legible policy. The plan endpoints exist so you write that once and attach it to customers, instead of hand-setting numbers per account and discovering the drift a quarter later.

Why one endpoint costs 1 credit and another costs 250

This is where the abstraction starts paying rent. Look at a real published credit table. Tavily's, read on 11 August 2026:

Operation

Credit cost

Search (basic)

1 per request

Search (advanced)

2 per request

Extract (basic)

1 per 5 successful URL extractions

Extract (advanced)

2 per 5 successful URL extractions

Map

1 per 10 successful pages

Research (mini)

4 to 110 per request

Research (pro)

15 to 250 per request

Tavily prices a credit at $0.008 on pay-as-you-go, and as low as $0.005 per credit on its monthly plans. Three distinct patterns are visible in that one table, and between them they cover most of what credit pricing is for:

  • A depth multiplier. Basic costs 1, advanced costs 2. Same endpoint, different work behind it.

  • Sub-unit batching. "1 per 5 successful extractions" means a single HTTP request can cost a fraction of a credit or dozens of them. The request stopped being the unit entirely, which is the clearest demonstration of the whole idea.

  • Open-ended ranges. Research runs 4 to 110 credits. That is honest, and it is also unbudgetable. Nobody can plan against a range that wide, so a provider who publishes one should expect customers to cap it themselves or avoid the endpoint.

Credits are not only about money, either. Google meters the YouTube Data API in units rather than dollars: projects get a daily allocation of 10,000 units shared across most endpoints, plus separate budgets of 100 calls each for search.list and videos.insert. Same mechanic, no invoice attached. The denominator is a design decision even when nothing is being sold.

Which points at the truth under all of this: a published credit table is your cost model, made public. If a credit price does not track what an operation actually costs you to serve, customers will find the underpriced route and use only that one. Working out those numbers is its own exercise, and we wrote it up separately in how to decide what one credit is worth.

The question nobody answers: what does a failed request cost?

Here are three real, published policies from three providers. All three are defensible. No two agree.

Provider

Policy on failures

YouTube Data API

Every request costs at least one unit, including invalid ones. You are charged for being wrong.

Tavily

A URL extraction that fails is never charged, and the same applies to failed mapping.

ReqKey

The credit check runs last, after key existence, key status, consumer status, expiry and API access. A revoked, expired or wrong-API key is refused before any deduction happens.

That third one is worth spelling out because the mechanism matters more than the promise. Those failures are free by construction, not by refund policy. Nothing has to be given back, because nothing was ever taken. Any system that deducts first and reverses later is a system where the reversal can fail.

So does a 500 on the provider's side cost you a credit? Frequently, yes, and that is the single case where it never should. If you are integrating against a credit-metered API, go and find the failure policy before you write the retry logic. If you cannot find it published anywhere, assume you are being charged, because the implementation that charges first is the easier one to write and most people write the easy one. If you are on the other side of that question and building the meter yourself, the ordering traps are covered in why your credit system bills before it knows the request worked.

402 is not 429, and your retry loop cares

Credits meter how much. Rate limits meter how fast. They are independent axes, and a surprising amount of client code treats them as the same thing.

  • 402 Payment Required means the balance is exhausted. Retrying changes nothing until a refill lands or someone tops the account up.

  • 429 Too Many Requests means you are going too fast. Backing off genuinely works, and the request is usually still affordable.

A client that treats both as "wait a moment and try again" will sit in a hot loop against a 402 until somebody notices. It never recovers, because nothing about waiting fixes an empty balance. ReqKey's error documentation makes the same point from the provider side: a 402 is not an outage, so surface it to the customer instead of retrying at it.

The two axes really are independent. A customer with unlimited credits can still be rate limited, and a customer with a healthy balance can still be throttled for bursting. Handle them separately:

from reqkey import ReqKey, VerificationReason

client = ReqKey.from_env()  # reads REQKEY_PROJECT_KEY

def authorize(api_key: str, cost: int):
    result = client.verify(api_key, credits=cost, resource="/v1/exports")

    if result.valid:
        return True

    if result.reason is VerificationReason.INSUFFICIENT_CREDITS:
        # Out of quota. Retrying will not help. Tell the customer.
        raise OutOfCredits(remaining=result.credits_remaining)

    if result.reason is VerificationReason.RATE_LIMITED:
        # Too fast, not out of money. Backing off actually works.
        raise SlowDown(retry_after=result.retry_after)

    raise Unauthorized(result.message)

Two failures, two branches, two completely different things to tell the user. Collapsing them into one except block is how you end up explaining to a customer why your integration hammered an empty account for six hours.

What it looks like on the wire

Mechanically, metering a request means naming its cost at the moment you check permission. In ReqKey that is a single call, and the cost is a parameter of it:

curl -X POST "https://api.reqkey.com/key/validate" \
  -H "Authorization: Bearer reqkey_xxx..." \
  -H "Content-Type: application/json" \
  -d '{
    "key": "prod_A1B2C3D4E5F6G7H8I9J0K1L2",
    "credits": 25,
    "resource": "/v1/exports"
  }'

A successful check answers with the decision and the balance in one response:

{
  "valid": true,
  "requestId": "abc123xyz",
  "creditsRemaining": 9975,
  "creditsLimit": 10000,
  "resource": "/v1/exports"
}

An exhausted balance answers 402, and says so in a way the client can act on:

{
  "valid": false,
  "message": "Credit limit exceeded",
  "creditsRemaining": 0,
  "creditsLimit": 10000
}

Three details in there are worth more than they look:

  • credits is a number, not a flag, and it defaults to 1. Per-endpoint pricing is just passing a different number for a different route.

  • credits: 0 runs the whole check and deducts nothing. That is your pre-flight: confirm a key is live and in good standing without charging for the privilege.

  • Non-integer values are rounded down. Send 2.5 and you charge 2. If you were planning to express fractional pricing by sending decimals, you would be quietly undercharging on every call, forever. The Python SDK refuses non-integers outright with a configuration error, which is the better place to find out.

That rounding rule is the sort of thing that never appears in an article about credit pricing and always appears in a reconciliation meeting. Ask me how I know.

Where credits stop

Two honest boundaries, because a definitional post that only sells is not a definition.

Credits are a metering primitive, not a billing system. Metering answers two questions: how much has this customer consumed, and may they continue. Invoicing, tax, dunning and proration are a different product with a different failure mode. ReqKey meters usage and tracks balances. It does not invoice your customers, and a plan's pricing block is a rate card you can read back rather than something we charge against. If you want the meter and the invoice in one place, that is a billing platform, and you should buy one.

There is no per-request undo. Putting credits back is possible, but the two ways to do it behave differently: a recharge is additive to the limit, which raises the ceiling, while correcting recorded usage writes an absolute value. Reverse enough charges with recharges and your "10,000 credit plan" drifts upward in your own reporting until the number means nothing. Decide which one you are using before you need it at 2am.

If credit metering is genuinely new to you, this AWS re:Invent session on treating usage-based billing as infrastructure is a good hour, and it argues the organisational case better than a blog post can:

AWS re:Invent 2025 talk: Why Usage-Based Billing Must Be Treated as Infrastructure

Key takeaways

  • A credit is a unit you define, and that is the entire point. If every operation costs one credit, you have renamed "request" and made your pricing page harder to read. Adopt credits when the cost of an operation genuinely varies, not because competitors use the word.

  • A credit balance is four decisions: limit, remaining, refill, overage. Write each one down before launch. The refill policy in particular (reset, add, or carryover with a cap) is the one your customers will ask about first and the one most providers leave undocumented.

  • Put remaining in the response that spends it. A client that sees its balance on every call can slow down, batch, or warn a human. A client that has to call a separate endpoint finds out by being refused.

  • Find the failure policy before you integrate. Three providers in this post charge for failures in three different ways. If a provider does not publish theirs, assume failures cost you, and budget accordingly.

  • 402 and 429 need separate branches in your client. One means "you are out", the other means "you are early". A retry loop that cannot tell them apart will burn against an empty balance indefinitely.

Try the mechanics against real traffic

Reading about refill policies is not the same as watching one behave. If you want to model a credit table against your own endpoints, ReqKey's free tier is $0 and includes 100,000 requests a month, which is enough to point a real integration at it, set a per-route credit cost, and see what your traffic actually spends before anyone is billed for anything. The plans and credits page covers how the pieces fit together, and the concepts documentation has the field-by-field reference.

Share this post

Put your API keys on autopilot.

Keys, credits, plans, and real-time traffic analytics — free for your first 100k requests a month.