Core concepts
Six ideas explain the whole API: the resource hierarchy, consumer-level credits, how a credit pool behaves, consumer rate limits, the lifecycle of each resource, and how state stays consistent across regions.
Resource hierarchy
A customer (you) can own many projects; each project is an isolated workspace with its own root key. Inside a project you create APIs (the services you meter), plans (optional credit templates), and consumers (your customers). Each consumer owns one or more keys.
ProjectYour workspace. Addressed by a rootKey; owns everything below it.
APIA service you meter. Keys can be scoped to specific APIs by apiId.
PlanA reusable bundle of credit limit + refill + overage + pricing.
ConsumerOne of your customers. Owns the credit pool. This is where billing lives.
KeyAn auth token your customer sends. Shares its consumer’s pool; no credits of its own.
Consumer-level credits
The single most important rule in ReqKey: credits live on the consumer, not the key. If a consumer has a 5,000-credit pool, then every key it owns — one or fifty — draws from that same 5,000. This prevents the classic billing leak where five keys silently multiply a plan into five separate quotas.
When you create a consumer, you choose one of three credit modes (in priority order):
1 · Direct
Pass a credits object. Highest priority.
{
"name": "Acme Corp",
"credits": {
"limit": 5000,
"shadowLimit": 500
}
}2 · From a plan
Pass a planId to inherit its credits.
{
"name": "Acme Corp",
"planId": "plan_enterprise"
}3 · Unlimited
Omit both. Validation never enforces a limit.
{
"name": "Internal Team"
}/consumer/update, or add credits without changing the limit via /key/recharge. Downgrading a plan? Send credits.used: 0 so remaining never goes negative.Credit mechanics
A consumer’s credit object is made of a few moving parts:
limitTotal pool size. remaining = limit − used.
usedCredits consumed so far. Deducted on each successful validation.
shadowLimitA soft threshold below the hard limit — fires low-credit warnings before the customer is cut off.
refillAuto top-up on an interval: { interval: "month", amount: 5000 }. Intervals: hour, day, week, month.
overageControlled spillover past the limit: { enabled: true, limit: 500 }.
expiresAtOptional millisecond timestamp after which the credits expire.
On /key/validate the requested credit amount (default 1) is deducted from the pool. Non-integer amounts round down; credits: 0 does a free check with no deduction.
Consumer rate limits
Credits meter how much a consumer can use; a rateLimit meters how fast. { "limit": 100, "window": 60 } allows 100 /key/validate requests per 60 seconds — the window is always in seconds and defaults to 1. Enforcement is a sliding window: a burst can never exceed limit requests, and a client sending steadily at exactly its limit is never spuriously throttled. Past the limit, validation returns 429 with a Retry-After header.
Consumer-levelOne limit shared by every key the consumer owns — there are no key-level rate limits.
Independent of creditsA consumer with unlimited credits can still be rate-limited.
429s are freeA denied request consumes no credits and no rate-limit quota, so a throttled client recovers as soon as it slows down.
Plan inheritanceA plan’s rateLimit is copied to the consumer at attach time, exactly like plan credits. Changing the plan later doesn’t touch consumers already on it.
Per-region windowsEach region enforces its own window. End users are pinned to one region, so they experience the configured limit; a client deliberately spraying requests across regions can reach up to limit × regions.
rateLimit on /consumer/create or /consumer/update — changes reach the validation hot path within ~200ms. Send { "rateLimit": null } to remove the limit entirely, even while the consumer is on a plan that has one.States & lifecycle
Consumers and keys move through a small set of states. A consumer’s status is a master switch: set a consumer to disabled and every one of its keys stops validating instantly — without touching each key — which is exactly what you want on a failed payment. Flip it back to active and they all resume.
activeNormal operation. Validates and deducts credits.
disabledBlocked from validation. On a consumer, this blocks all its keys.
pendingCreated but not yet enabled (keys only).
deletedSoft-deleted and recoverable — 7 days for consumers & keys, 30 days for APIs.
permanent: true. Restore a consumer (and its keys) by updating its status back to active within the recovery window. Hard delete is irreversible and also clears credit state.Regions & consistency
Validation runs in whichever region is closest to your servers, so answers come back in single-digit milliseconds. Behind it, ReqKey’s credit engine keeps every region’s balances in step through a global sync layer, and a reconciler heals any missed update within about a second. Recharges and limit changes propagate to all regions immediately — you never have to think about which region a key was created in.