every model spec’d & versioned · Concordance-tested changelog →

Resources · Engineering & integration

Rate Limits and What Is Actually Metered

One enforced backstop, no run quota at all, and a meter that counts stored households rather than calls. What to build against, and what not to bother building.

By Worthune Staff · 2026-08-14

Most rate-limit documentation makes integrators build for a wall that will never be hit. Worthune publishes two numbers with two different natures — and the right client architecture follows from knowing which is which.

Every vendor integration eventually has the rate-limit conversation, and it usually happens twice: once when an engineer reads the docs and once when something returns a 429 in production. This piece is the whole conversation in one place: what the two published numbers mean, what the client should actually do about each, and what is safe to cache.

The hard number: 120 per minute, per IP

The only enforced limit is a burst backstop: 120 requests a minute per IP. Exceed it and the API returns HTTP 429 with a retry-after header stating how long to wait. Its purpose is narrow — stopping runaway loops and script accidents, not metering real usage. A user filling in a form, or even a busy product server fanning out requests for a page render, does not approach two requests a second sustained for a minute from one address.

Handling the 429
if status == 429: wait retry-after seconds, then retry the same request once; if it recurs, surface it — a loop is running somewhere

The retry-after header is the contract: honor it rather than guessing with exponential backoff from zero. And treat a recurring 429 as a bug report about your own code, because at 120 per minute per IP, sustained hits almost always mean an unintended loop — a useEffect without a dependency array, a retry storm, a load test pointed at production.

One distinction spares a lot of wasted retry logic: 429 is the only response worth retrying automatically. A validation failure is deterministic — the same rejected input will be rejected identically every time, so retrying it is a tight loop that produces nothing but progress toward the backstop. Retry on 429 with the header's delay; on ok: false, fix the input instead.

The number that does not exist: a run quota

There is no monthly run allowance, and the pricing page commits to there never being one: model runs are not metered at any tier. What a plan meters is stored households — a household counts as active in a month it was created or recomputed, dormant records cost nothing — so the number worth watching is how many households you keep, not how many times you compute. Running the household engine without storing anything needs no key and no plan at all.

The architectural consequence: do not build quota-tracking infrastructure for runs. Teams arriving from APIs that meter calls add counters, alerts and degradation paths for a wall that does not exist here. Track stored households if you are on a plan, because that is what the invoice reflects; track request volume for your own capacity planning; do not build a run budget.

NumberNatureClient response
120 requests per minute per IPEnforced backstop with 429 and retry-afterHonor the header and investigate recurrences as bugs
Model runsNever metered, at any tier, by published commitmentCompute as often as the product needs; build no run budget
Active householdsThe actual meter: created or recomputed in the monthSize the plan against this, and read the per-household overage rate

What is safe to cache

Caching is the legitimate way to keep a chatty product under any limit, and the envelope's own structure says what is cacheable. A model run is deterministic: the same model, spec version, and inputs produce the same outputs — the whole verification story depends on it. So a cache keyed on model plus specVersion plus the canonical inputs is sound, and the record’s canonical-JSON convention doubles as the key-serialization recipe. Two rules keep it honest:

The subtle item is the fourth. A cached envelope contains, say, a contribution limit inside its facts array — accurate for the run it describes. Copying that number out of the cache into your own code turns a cited, dated constant into an undated hard-coded one, and next January it is quietly wrong. The envelope is cacheable as a unit; its constants are not extractable as facts that stand alone.

Interactive surfaces: debounce, do not meter

A slider wired directly to the API generates a request per pixel of drag — the one realistic way a legitimate UI approaches the burst backstop. The fix is standard front-end hygiene, not rate-limit engineering: debounce to one request per settled value, cancel in-flight requests when a newer one supersedes them, and render the last result while the next loads. A debounced slider lands at a handful of requests per user interaction, which is nowhere near any number on this page.

Where usage is public

One more number worth knowing exists: Worthune publishes its own aggregate usage at /api/v1/telemetry — daily hit counts per surface for the last thirty days, with an explicit privacy note that only aggregate counters are stored, never IPs, user agents, or inputs. For an integrator, that endpoint is a transparency artifact: the platform holding your dependency shows its own traffic shape in public, the same show-your-work posture as the specs.

Sources

  1. [1] Worthune pricing (the backstop and the meter, in writing). https://worthune.com/pricing
  2. [2] Worthune API documentation. https://worthune.com/docs