Error Codes
Starting with API version 2026-01-01, error responses use a simplified, consistent format. Version 2026-03-01 adds IP resolution error types.
All errors return a JSON object with three fields:
{
"code": 400,
"type": "ZIP_STATE_MISMATCH",
"message": "Unable to create calculation. address_zip_code 92037 not found in the address_province TN. Ensure zip is up to date and formed correctly."
}
| Field | Type | Description |
|---|
code | integer | HTTP status code |
type | string | Machine-readable error type (use this for programmatic handling) |
message | string | Human-readable description of the error |
Previous API versions used a nested error object. The 2026-01-01+ format is flattened for easier parsing.
Error Types Reference
Validation Errors
These errors occur when request data is invalid or malformed.
| Type | Description |
|---|
ERROR | Generic error |
MISSING_FIELD | A required field was not provided |
INCORRECT_TYPE | A field has the wrong data type |
UNRECOGNIZED_FIELD | An unknown field was included in the request |
NEGATIVE_NUMBER_REQUIRED | Field requires a negative number |
POSITIVE_NUMBER_REQUIRED | Field requires a positive number |
INVALID_EMAIL | Email address format is invalid |
Address Errors
These errors relate to address validation issues.
| Type | Description |
|---|
MALFORMED_ADDRESS | Address format is invalid or incomplete |
ZIP_STATE_MISMATCH | ZIP/postal code does not match the provided state/province |
MISSING_ORIGIN_ADDRESS | Origin address is required but not provided (check merchant default address) |
INVALID_COUNTRY_CODE | Country code is not recognized (use ISO 3166-1 alpha-2) |
IP Resolution Errors
These errors relate to IP-based tax resolution (new in 2026-03-01).
| Type | HTTP Code | Description |
|---|
INVALID_IP_FORMAT | 400 | ip.value must be a valid IPv4 or IPv6 address |
IP_RESOLUTION_FAILED | 422 | Unable to resolve IP address to a country. Provide a full address in customer.address. |
IP_RESOLUTION_INSUFFICIENT_US | 422 | IP resolved to a US state but could not determine a postal code. Provide address_postal_code and address_province in customer.address. |
IP_RESOLUTION_INSUFFICIENT_CA | 422 | IP resolved to CA but could not determine a province. Provide address_province in customer.address. |
IP resolution errors only occur when using customer.ip with resolution: "strict" (the default). Use "best_effort" or "zero" to avoid these errors and receive zero-rate responses instead.
Product Errors
These errors relate to product operations.
| Type | Description |
|---|
PRODUCT_NOT_FOUND | The specified product ID does not exist |
DUPLICATE_PRODUCT | A product with this reference ID already exists |
INVALID_TAX_CODE | The product tax code is not valid |
INVALID_PRODUCT_CATEGORY | The product category is not recognized |
Customer Errors
These errors relate to customer operations.
| Type | Description |
|---|
CUSTOMER_NOT_FOUND | The specified customer ID does not exist |
DUPLICATE_CUSTOMER | A customer with this reference ID already exists |
Merchant Errors
These errors relate to merchant operations (new in 2026-01-01).
| Type | Description |
|---|
MERCHANT_NOT_FOUND | The specified merchant ID does not exist |
DUPLICATE_MERCHANT | A merchant with this reference ID already exists |
MERCHANT_CREATION_FAILED | Failed to create the merchant |
MERCHANT_UPDATE_FAILED | Failed to update the merchant |
Calculation Errors
These errors relate to tax calculation operations.
| Type | Description |
|---|
CALCULATION_NOT_FOUND | The specified calculation ID does not exist |
CALCULATION_EXPIRED | The calculation has expired and can no longer be used |
INVALID_CURRENCY_CODE | Currency code is not supported (see supported currencies) |
Transaction Errors
These errors relate to transaction operations.
| Type | Description |
|---|
TRANSACTION_NOT_FOUND | The specified transaction ID does not exist |
TRANSACTION_ALREADY_EXISTS | A transaction with this calculation ID already exists |
REFERENCE_ORDER_ID_ALREADY_EXISTS | A transaction with this reference order ID already exists |
HTTP Status Codes
| Code | Meaning |
|---|
400 | Bad Request - Invalid parameters or validation error |
401 | Unauthorized - Invalid or missing API key |
404 | Not Found - Resource does not exist |
409 | Conflict - Resource already exists (duplicates) |
422 | Unprocessable Entity - Request understood but cannot be processed (includes IP resolution errors) |
429 | Too Many Requests - Rate limit exceeded |
500 | Internal Server Error - Something went wrong on our end |
Handling Errors
Example Error Handling
try {
const response = await fetch('https://api.numeralhq.com/tax/calculations', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_xxx',
'X-API-Version': '2026-03-01',
'Content-Type': 'application/json'
},
body: JSON.stringify(calculationData)
});
if (!response.ok) {
const error = await response.json();
switch (error.type) {
case 'ZIP_STATE_MISMATCH':
// Prompt user to verify their address
break;
case 'PRODUCT_NOT_FOUND':
// Create the product first
break;
case 'CALCULATION_EXPIRED':
// Request a new calculation
break;
case 'IP_RESOLUTION_FAILED':
// Fall back to asking for a full address
break;
case 'IP_RESOLUTION_INSUFFICIENT_US':
// Ask for ZIP code and state
break;
case 'IP_RESOLUTION_INSUFFICIENT_CA':
// Ask for province
break;
case 'INVALID_IP_FORMAT':
// Check IP address format
break;
default:
console.error(`Error: ${error.message}`);
}
}
} catch (err) {
// Handle network errors
}
Best Practices
- Always check the
type field for programmatic error handling
- Display the
message field to users when appropriate
- Log the full error response for debugging
- Handle specific error types rather than just checking status codes
- Use
resolution: "best_effort" if you want to avoid IP resolution errors and prefer zero-rate fallbacks