Skip to main content

API Usage Scores

Every API call consumes points equal to the score of the endpoint it hit. Points accumulate per client per month under monthly_limit; once the limit is exceeded the middleware cuts the response off with HTTP 429.

What a call actually costs

GET /v2/health is free. Every other endpoint costs 1000.

Treat that as the contract. Do not build per-endpoint cost assumptions on top of it — budget with the X-MonthlyLimit-* headers instead, which always report the truth.

Why it is a flat rate today

The UsageLimit middleware looks each request up in the server-side usage.EndpointScores map (contexts/integration/aggregates/usage/usage.go) with the key <METHOD> <route template>, falling back to DefaultScore = 1000 when there is no match. The lookup uses the matched route pattern (/v2/admin/tokens/:tokenID/burn), so parameterised endpoints resolve correctly.

The flat rate is therefore a pricing decision, not a defect: every endpoint listed in the map is currently priced at DefaultScore, so a listed endpoint costs a caller exactly the same as an unlisted one. GET /v2/health is the single entry whose value changes an outcome.

If endpoints are priced differently later, only the map changes — the lookup already resolves the right key.

Monthly counter

  • The counter lives in Redis under monthly-usage-{clientID}-{YYYY-MM}.
  • On a cache miss it is summed from the usages collection in MongoDB and re-cached. A legitimate zero is distinguished from a miss by returning *int64, so a client that has spent 0 points does not fall through to Mongo on every request.
  • After each successful request the counter is incremented by that request's score.
  • When the monthly limit is exceeded the middleware answers:
    • HTTP 429 Too Many Requests
    • X-MonthlyLimit-Limit, X-MonthlyLimit-Used, X-MonthlyLimit-Remaining headers
    • The counter resets at the start of the next month (the YYYY-MM key changes).

Reading your remaining budget

Every response carries the headers below. They are computed from the live counter, so they stay correct regardless of how scoring is configured:

HeaderMeaning
X-MonthlyLimit-LimitThe client's monthly point allowance
X-MonthlyLimit-UsedPoints consumed so far this month
X-MonthlyLimit-RemainingPoints left before requests start returning 429

429 response

{
"code": 10029,
"domain": 20,
"message": "monthly usage limit exceeded"
}

Notes

  • Scores are per client, not per user or per node.
  • A request that fails validation still reaches the middleware and is counted.
  • If per-endpoint pricing is introduced later only the scores in the map change; the keys already name real routes and the lookup already resolves them. Until then the flat rate above is the only behaviour to design against.