ReqKeydocs
Guides

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.

Project

Your workspace. Addressed by a rootKey; owns everything below it.

API

A service you meter. Keys can be scoped to specific APIs by apiId.

Plan

A reusable bundle of credit limit + refill + overage + pricing.

Consumer

One of your customers. Owns the credit pool. This is where billing lives.

Key

An 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"
}
Changing credits later
Resize a pool anytime with /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:

limit

Total pool size. remaining = limit − used.

used

Credits consumed so far. Deducted on each successful validation.

shadowLimit

A soft threshold below the hard limit — fires low-credit warnings before the customer is cut off.

refill

Auto top-up on an interval: { interval: "month", amount: 5000 }. Intervals: hour, day, week, month.

overage

Controlled spillover past the limit: { enabled: true, limit: 500 }.

expiresAt

Optional 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-level

One limit shared by every key the consumer owns — there are no key-level rate limits.

Independent of credits

A consumer with unlimited credits can still be rate-limited.

429s are free

A denied request consumes no credits and no rate-limit quota, so a throttled client recovers as soon as it slows down.

Plan inheritance

A 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 windows

Each 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.

Setting, changing, removing
Set 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.

active

Normal operation. Validates and deducts credits.

disabled

Blocked from validation. On a consumer, this blocks all its keys.

pending

Created but not yet enabled (keys only).

deleted

Soft-deleted and recoverable — 7 days for consumers & keys, 30 days for APIs.

Soft delete by default
Delete endpoints soft-delete unless you pass 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.