> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.zip.tax/v-6-0/guides/reference/response-codes/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.zip.tax/_mcp/server. # Response Codes Every Ziptax response carries an application-level response code in addition to the HTTP status. The code tells you what happened in business terms (success, bad input, plan-gated feature, quota exhausted, and so on) and is the signal your integration should branch on. ## Response envelope Both success and error responses use the same envelope. The code lives at `metadata.response`: ```json { "metadata": { "version": "v60", "response": { "code": 100, "name": "RESPONSE_CODE_SUCCESS", "message": "Successful API Request.", "definition": "http://api.zip-tax.com/request/v60/schema" } } } ``` > **Info** > > Legacy versions (v50 and earlier) return the same fields at the top > level as `rCode`, `rName`, and `rMessage` instead of nested under > `metadata.response`. The numeric codes are identical across all > versions. ## Full list | Code | Name | HTTP | Message | | ------: | ----------------------------------------- | ---: | --------------------------------------------------------------------------------------------------------- | | **100** | `RESPONSE_CODE_SUCCESS` | 200 | Successful API Request. | | **101** | `RESPONSE_CODE_INVALID_KEY` | 401 | Key format is not valid or key not found. | | **102** | `RESPONSE_CODE_INVALID_STATE` | 422 | The provided State is not in a valid format parsable by the API. | | **103** | `RESPONSE_CODE_INVALID_CITY` | 422 | The provided City is not in a valid format parsable by the API. | | **104** | `RESPONSE_CODE_INVALID_POSTAL_CODE` | 422 | The provided Postal Code is not in a valid format parsable by the API. | | **105** | `RESPONSE_CODE_INVALID_FORMAT` | 422 | Query string format is not valid. | | **106** | `RESPONSE_CODE_API_ERROR` | 500 | Unknown API error. | | **107** | `RESPONSE_CODE_FEATURE_NOT_ENABLED` | 405 | Requested feature or version not enabled for your current plan. Upgrade your plan to access this feature. | | **108** | `RESPONSE_CODE_REQUEST_LIMIT_MET` | 429 | API request limit met. | | **109** | `RESPONSE_CODE_ADDRESS_INCOMPLETE` | 422 | The provided address is missing, incomplete, or not a valid address. | | **110** | `RESPONSE_CODE_NO_RESULT` | 422 | Query parameters valid but no result found. | | **111** | `RESPONSE_CODE_INVALID_HISTORICAL` | 422 | The provided historical parameter is not in a valid format. | | **112** | `RESPONSE_CODE_INTERNATIONAL_NOT_ENABLED` | 403 | International rates not enabled for this key. | | **113** | `RESPONSE_CODE_PRODUCT_RULES_NOT_ENABLED` | 403 | Product rate rules not enabled for this key. | ## When you'll see each ### 100, Success The lookup completed and the response contains rate data. Always check for `100` before reading `baseRates` or `taxSummaries`. ### 101, Invalid key The `X-API-KEY` header (or `key=` query parameter) is missing, malformed, or doesn't match a key in our database. Check for trailing whitespace, encoding issues, or using the wrong environment's key. ### 102 to 105, Input validation The state, city, postal code, or overall query string isn't in a shape Ziptax can parse. These are deterministic, so re-sending the same request will always fail the same way. Fix the input before retrying. ### 106, Unknown API error Something went wrong on our end. Safe to retry with exponential backoff. If you see these persistently, email [support@zip.tax](mailto:support@zip.tax). ### 107, Feature not enabled The API version or feature you requested isn't available on your plan (for example, calling `/request/v60` on a plan that only includes v40). Upgrade your plan or use a supported version. ### 108, Rate limit You've sent more requests than your per-minute `request_rate` entitlement allows within the current 60-second sliding window. The response includes `X-RateLimit-Limit` and `X-RateLimit-Remaining` headers. See [Rate Limiting & Errors](./rate-limiting-errors) for backoff guidance. ### 109, Address incomplete The address (or lat/lng, or postal code) you sent couldn't be resolved to a real location. Common causes: missing street number, obviously wrong ZIP for the city, coordinates in the middle of the ocean, or a typo that leaves the geocoder unable to disambiguate. ### 110, No result Parameters were valid but nothing matched. Most common on historical lookups where the date precedes our coverage, or niche international territories. ### 111, Invalid historical The `historical` parameter wasn't accepted. Use the format `YYYYMM` (6 digits, no separator, e.g. `202401` for January 2024). The API also rejects the current month, any future month, and months older than the service's historical coverage window. ### 112, International not enabled You passed `countryCode=CAN` (or another non-USA country) but your account doesn't have the `rate_loc_can` entitlement. Upgrade to Pro or Enterprise to unlock Canadian lookups. ### 113, Product rules not enabled You passed `taxabilityCode=...` but your account doesn't have the `product_rates` entitlement. Upgrade to Pro or Enterprise to unlock product-specific rate rules. See [Taxability Information Codes](../product-rules/taxability-information-codes) for what this parameter does. ## Handling codes programmatically Branch on the numeric `code`, not the HTTP status or message text. The messages are documented here for humans but may be refined over time. The codes are stable. #### Python ```python import requests res = requests.get( "https://api.zip-tax.com/request/v60", headers={"X-API-KEY": "YOUR_API_KEY"}, params={"address": "200 Spectrum Center Dr, Irvine CA"}, ) data = res.json() code = data["metadata"]["response"]["code"] if code == 100: rate = data["taxSummaries"][0]["rate"] elif code == 108: # back off, respect X-RateLimit-* headers ... elif code in (112, 113): # feature not on this plan; show an upsell or skip silently ... elif code == 109: # address didn't resolve; prompt the user to fix it ... else: # log, alert, and fail closed ... ``` #### Node.js ```javascript const res = await fetch( "https://api.zip-tax.com/request/v60?address=" + encodeURIComponent("200 Spectrum Center Dr, Irvine CA"), { headers: { "X-API-KEY": "YOUR_API_KEY" } } ); const data = await res.json(); const code = data.metadata.response.code; switch (code) { case 100: // success break; case 108: // rate limit; back off break; case 112: case 113: // plan-gated feature break; case 109: // bad address break; default: // log + alert } ``` #### Go ```go type Response struct { Metadata struct { Response struct { Code int `json:"code"` Name string `json:"name"` } `json:"response"` } `json:"metadata"` } var r Response _ = json.NewDecoder(res.Body).Decode(&r) switch r.Metadata.Response.Code { case 100: // success case 108: // rate limit case 112, 113: // plan-gated case 109: // bad address default: // log + alert } ``` ## Retry guidance at a glance | Code | Retry safe? | Notes | | -------------------- | ----------- | -------------------------------------------------------- | | 100 | n/a | Success. No retry needed. | | 101 | No | Fix the key and retry once. | | 102 to 105, 109, 111 | No | Input is bad; retrying won't change anything. | | 106 | Yes | Transient server error. Exponential backoff. | | 107, 112, 113 | No | Plan-gated. Upgrade the plan or skip the call. | | 108 | Yes | Back off until `X-RateLimit-Remaining` resets. | | 110 | No | Try a different query (broader address, different date). | ## Related #### [Rate Limiting & Errors](rate-limiting-errors) Deeper dive on 429/108 behavior, headers, and backoff. #### [Taxability Information Codes](../product-rules/taxability-information-codes) What `taxabilityCode` does and why code 113 shows up. #### [REST API](../rest-api/overview) How the endpoints that return these codes are called. > Every application-level code Ziptax can return, what it means, and how to handle it