Skip to Content
REST APIUsage & quotas

Usage, quotas and rate-limit semantics

GET /v1/account/usage

Reads your account’s current request-unit usage for the active billing period.

This endpoint is Session-authenticated only — an API-key holder cannot call it directly over REST. If your integration uses an API key (not a human session), read usage programmatically via the get_usage MCP tool → instead, which is API-key-authenticated and returns the byte-identical response shape.

Auth

Authorization: Session <token> — required.

Missing/invalid/expired session → 401 unauthorized:

{ "code": "unauthorized", "message": "Authentication required.", "request_id": "..." }

Success — 200

curl https://your-getratesapi-host/v1/account/usage \ -H "Authorization: Session gra_sess_0000000000000000000000000000000000000000000"
const res = await fetch("https://your-getratesapi-host/v1/account/usage", { headers: { Authorization: "Session gra_sess_0000000000000000000000000000000000000000000", }, }); const usage = await res.json();
{ "plan": "free", "billing_period": { "start": "2026-10-01T00:00:00Z", "end": "2026-11-01T00:00:00Z" }, "usage": { "used_units": 123, "quota_units": 500, "remaining_units": 377, "utilization": 0.246 } }

utilization is a pre-rounded ratio (4 decimal places) computed server-side — never recompute it client-side.

The response always sends Cache-Control: no-store.

Failure

503 temporarily_unavailable on entitlement/storage failure.

Usage history

GET /v1/account/usage/history?days=30 (Session required) powers the charts in the dashboard. days is 7–90 (default 30). Every day in the window and every hour of the last 24 hours is present, zero-filled, so a chart needs no gap handling. Times are UTC.

curl "https://your-getratesapi-host/v1/account/usage/history?days=7" \ -H "Authorization: Session gra_sess_0000000000000000000000000000000000000000000"
{ "days": 7, "from": "2026-10-10T00:00:00Z", "to": "2026-10-16T18:55:02Z", "total_units": 44, "daily": [ { "date": "2026-10-16", "units": 44, "by_endpoint": { "rate": 26, "rates": 8, "convert": 10 } } ], "hourly": [ { "hour": "2026-10-16T18:00:00Z", "units": 44 } ], "by_endpoint": [ { "endpoint": "rate", "units": 26 }, { "endpoint": "rates", "units": 8 }, { "endpoint": "convert", "units": 10 } ], "by_key": [ { "key_id": "e2317be7-c508-4e0c-b620-821e4c722dbe", "name": "Website", "key_prefix": "gra_live_fb7318ed", "revoked": false, "units": 34 }, { "key_id": null, "name": "", "key_prefix": "", "revoked": false, "units": 8 } ] }

(daily and hourly are shortened here.) endpoint is rate (single pair), rates (multi-quote), convert, mcp, or other for usage recorded before endpoint tracking existed. A by_key entry with key_id: null is usage from a key you have since deleted. by_key lists the top 10 keys.

Billing periods and long terms

The quota is monthly. On a 3-, 6- or 12-month plan the allowance resets every month from the day the term started, so a yearly Developer plan gets 50,000 requests each month, not 600,000 for the year. A paid upgrade raises the current month’s quota immediately.

Request-unit quota vs. auth rate limiting — two different 429 causes

There are two unrelated mechanisms that can return HTTP 429. Always distinguish them by code, never by status code alone:

codeWhere it happensMeaning
quota_exceededcurrent-rate endpoint, MCP get_rate/convert_currencyYour billing-period request-unit quota is exhausted
too_many_requestsregister, login, password-reset/verification-resend onlyA separate, fixed-window IP+email abuse budget on auth endpoints has been exceeded

The auth-abuse rate limiter has nothing to do with your request-unit quota — hitting one never affects the other.