> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.zip.tax/v-5-0/guides/reference/account-metrics/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.zip.tax/_mcp/server. # Account Metrics & Usage `GET /account/v{N}/metrics` returns the current usage and quota for the API key you pass. Replace `{N}` with the API version your key is on (`v10`–`v60`). Use it to show an in-app dashboard, set up alerting before you run out of quota, or debug an unexpected 108 by confirming your plan limits. > **Info** > > This endpoint reports **plan quota**: the total requests your plan > includes and how many you've used. It's a different thing from the > per-minute rate limit (which is `request_rate` and is documented on > [Rate Limiting & Errors](./rate-limiting-errors)). You can burn > through your monthly quota without ever tripping the per-minute limit, > and vice versa. ## Making the call Pass your API key as a query parameter (or as `X-API-KEY` header) to `GET /account/v{N}/metrics` (examples below use `v60`): #### cURL ```bash curl "https://api.zip-tax.com/account/v60/metrics?key=YOUR_API_KEY" ``` #### Python ```python import requests res = requests.get( "https://api.zip-tax.com/account/v60/metrics", headers={"X-API-KEY": "YOUR_API_KEY"}, ) metrics = res.json() print(f"{metrics['request_count']:,} / {metrics['request_limit']:,} used") ``` #### Node.js ```javascript const res = await fetch( "https://api.zip-tax.com/account/v60/metrics", { headers: { "X-API-KEY": "YOUR_API_KEY" } } ); const metrics = await res.json(); console.log(`${metrics.request_count} / ${metrics.request_limit} used`); ``` ## Response shape (v60) ```json { "request_count": 4215, "request_limit": 100000, "usage_percent": 4.215, "is_active": true, "message": "Contact support@zip.tax to modify your account" } ``` | Field | Type | Meaning | | --------------- | ------- | ------------------------------------------------------------------------- | | `request_count` | integer | Total requests made on this key this billing period. | | `request_limit` | integer | Total requests your plan includes. `0` means unmetered. | | `usage_percent` | number | `request_count / request_limit * 100`. | | `is_active` | boolean | `false` if the key has been disabled (billing issue, support hold, etc.). | | `message` | string | How to change plan or limits; always points at support. | ### Legacy response (v10–v50) Older API versions split the counters into `core_*` (tax lookups) and `geo_*` (geocoded lookups). All new keys use the v60 shape. If you're still on a legacy key, you'll see: ```json { "is_active": true, "core_request_count": 4215, "core_request_limit": 100000, "geo_request_count": 4215, "geo_request_limit": 100000, "geo_enabled": true, "core_usage_percent": 4.215, "geo_usage_percent": 4.215, "message": "Contact support@zip.tax to modify your account" } ``` > **Info** > > For v60 keys the counters are unified. Every lookup counts against > `request_limit`, regardless of whether it was by address or by > coordinates. ## Patterns ### Show a usage widget in your dashboard Poll once when the page loads, not on every render: ```javascript async function loadUsageWidget() { const res = await fetch( "https://api.zip-tax.com/account/v60/metrics", { headers: { "X-API-KEY": process.env.ZIPTAX_KEY } } ); const { request_count, request_limit, usage_percent } = await res.json(); document.querySelector("#used").textContent = request_count.toLocaleString(); document.querySelector("#limit").textContent = request_limit.toLocaleString(); document.querySelector("#bar").style.width = `${usage_percent}%`; } ``` ### Alert before you run out Check metrics on a schedule (hourly or daily is plenty) and page your team when you cross a threshold: ```python def check_quota(): res = requests.get( "https://api.zip-tax.com/account/v60/metrics", headers={"X-API-KEY": os.environ["ZIPTAX_KEY"]}, ) m = res.json() if m["usage_percent"] >= 80: page_team(f"Ziptax usage at {m['usage_percent']:.0f}%") if not m["is_active"]: page_team("Ziptax key is deactivated") ``` ### Debug an unexpected 108 If you're getting 108s but your plan shouldn't hit the rate limit, `/account/v{N}/metrics` can confirm your key is active and reachable. Remember: 108s come from the **per-minute** `request_rate`, not from `request_limit`, so a low `usage_percent` here doesn't rule out a 108. Check the `X-RateLimit-Limit` header on the 108 response instead. ## Authentication and errors The `/account/v{N}/metrics` endpoint uses the same API key auth as `/request/v*`: either `X-API-KEY` header or `key=` query parameter. If the key is missing, you'll get an HTTP 400 with a short error body: ```json { "error": "API key is required as a query parameter", "message": "The parameter 'key' is required" } ``` If the key is valid but not found in Ziptax's account database, the response is still HTTP 200 with zeros across the board and `is_active: false`. Check `is_active` before trusting the numbers. ## Related #### [Rate Limiting & Errors](rate-limiting-errors) The per-minute limit that's separate from plan quota. #### [Response Codes](response-codes) Every application-level code Ziptax can return. > Check your plan quota, usage, and account status with `/account/v{N}/metrics`